import uuid
from datetime import datetime

from fastapi import APIRouter, Body, Depends, HTTPException
from pydantic import BaseModel
from sqlalchemy.orm import Session

from common_logging import get_logger

logger = get_logger(__name__)

from app.database import get_db
from app.models.tax_data import DataProcessingTask
from app.tasks.processor_tasks import (
    backfill_attachment_content_task,
    backfill_media_task,
    build_relations_task,
    fill_content_text_task,
    fill_issuing_authority_task,
    fill_superseded_by_task,
    fix_json_null_task,
    incremental_update_task,
    process_category_task,
    redownload_missing_attachments_task,
    reprocess_from_local_task,
)

router = APIRouter()

class FullProcessRequest(BaseModel):
    category_ids: list[int] | None = None
    force: bool = False

class IncrementalUpdateRequest(BaseModel):
    category_ids: list[int] | None = None
    window_days: int = 7

@router.post('/full-process')
async def start_full_process(request: FullProcessRequest=Body(default=FullProcessRequest()), db: Session=Depends(get_db)):
    task_id = f'full_{uuid.uuid4().hex[:8]}'
    if request.category_ids:
        tasks = []
        for category_id in request.category_ids:
            task = DataProcessingTask(task_id=f'{task_id}_cat{category_id}', category_id=category_id, mode='full', status='pending', progress=0)
            db.add(task)
            tasks.append(task.task_id)
        db.commit()
        logger.bind(task_id=task_id).info("full process tasks created", category_count=len(tasks))
        for idx, category_id in enumerate(request.category_ids):
            process_category_task.delay(tasks[idx], category_id, 'full', request.force)
        return {'message': f'已创建 {len(tasks)} 个全量处理任务', 'task_ids': tasks, 'categories': request.category_ids}
    else:
        task = DataProcessingTask(task_id=task_id, category_id=None, mode='full', status='pending', progress=0)
        db.add(task)
        db.commit()
        logger.bind(task_id=task_id).info("full process task created for all categories")
        for category_id in range(1, 9):
            cat_task_id = f'{task_id}_cat{category_id}'
            process_category_task.delay(cat_task_id, category_id, 'full', request.force)
        return {'message': '全量处理任务已启动，正在处理8个分类', 'task_id': task_id, 'categories': 'all'}

@router.post('/incremental-update')
async def start_incremental_update(request: IncrementalUpdateRequest=Body(default=IncrementalUpdateRequest()), db: Session=Depends(get_db)):
    task_id = f'incr_{uuid.uuid4().hex[:8]}'
    task = DataProcessingTask(task_id=task_id, category_id=None, mode='incremental', status='running', progress=0, started_at=datetime.utcnow())
    db.add(task)
    db.commit()
    logger.bind(task_id=task_id).info("incremental update task created", window_days=request.window_days)
    incremental_update_task.delay(category_ids=request.category_ids, window_days=request.window_days, task_id=task_id)
    categories_desc = f'{len(request.category_ids)}个分类' if request.category_ids else '全部8个分类'
    return {'message': f'增量更新任务已启动，正在检查{categories_desc}（最近{request.window_days}天）', 'task_id': task_id, 'category_ids': request.category_ids or list(range(1, 9)), 'window_days': request.window_days}

def _to_local_time(dt):
    if not dt:
        return None
    from datetime import timedelta
    return (dt + timedelta(hours=8)).isoformat()

@router.get('')
async def list_tasks(status: str | None=None, skip: int=0, limit: int=20, db: Session=Depends(get_db)):
    query = db.query(DataProcessingTask)
    if status:
        query = query.filter(DataProcessingTask.status == status)
    total = query.count()
    tasks = query.order_by(DataProcessingTask.created_at.desc()).offset(skip).limit(limit).all()
    return {'total': total, 'items': [{'id': task.id, 'task_id': task.task_id, 'category_id': task.category_id, 'mode': task.mode, 'status': task.status, 'progress': task.progress, 'total_count': task.total_count, 'success_count': task.success_count, 'failed_count': task.failed_count, 'error_message': task.error_message, 'started_at': _to_local_time(task.started_at), 'completed_at': _to_local_time(task.completed_at), 'created_at': _to_local_time(task.created_at), 'updated_at': _to_local_time(task.updated_at)} for task in tasks]}

@router.get('/scan-missing-attachments')
async def scan_missing_attachments(db: Session=Depends(get_db)):
    import os

    from app.models.tax_data import TaxDocument
    docs = db.query(TaxDocument.id, TaxDocument.title, TaxDocument.attachments).filter(TaxDocument.attachments.isnot(None)).all()
    missing = []
    for doc_id, title, attachments in docs:
        if not attachments:
            continue
        for idx, att in enumerate(attachments):
            path = att.get('path', '')
            if path and (not os.path.isfile(path)):
                missing.append({'doc_id': doc_id, 'title': title, 'attachment_idx': idx, 'name': att.get('name'), 'path': path, 'url': att.get('url')})
    return {'total_missing': len(missing), 'items': missing}

@router.post('/redownload-missing-attachments')
async def redownload_missing_attachments():
    redownload_missing_attachments_task.delay()
    return {'message': 'redownload_missing_attachments 任务已派发，完成后可查看日志'}

@router.get('/{task_id}')
async def get_task_detail(task_id: str, db: Session=Depends(get_db)):
    task = db.query(DataProcessingTask).filter(DataProcessingTask.task_id == task_id).first()
    if not task:
        raise HTTPException(status_code=404, detail='任务不存在')
    return {'id': task.id, 'task_id': task.task_id, 'category_id': task.category_id, 'mode': task.mode, 'status': task.status, 'progress': task.progress, 'total_count': task.total_count, 'success_count': task.success_count, 'failed_count': task.failed_count, 'error_message': task.error_message, 'started_at': _to_local_time(task.started_at), 'completed_at': _to_local_time(task.completed_at), 'created_at': _to_local_time(task.created_at), 'updated_at': _to_local_time(task.updated_at)}

@router.delete('/{task_id}')
async def cancel_task(task_id: str, db: Session=Depends(get_db)):
    task = db.query(DataProcessingTask).filter(DataProcessingTask.task_id == task_id).first()
    if not task:
        raise HTTPException(status_code=404, detail='任务不存在')
    if task.status in ['completed', 'failed', 'cancelled']:
        raise HTTPException(status_code=400, detail='任务已结束，无法取消')
    task.status = 'cancelled'
    task.completed_at = datetime.utcnow()
    db.commit()
    logger.bind(task_id=task_id).info("task cancelled")
    return {'message': '任务已取消', 'task_id': task_id}

@router.post('/fill-content-text')
async def fill_content_text(db: Session=Depends(get_db)):
    pending = db.query(DataProcessingTask).filter(DataProcessingTask.mode == 'fill_content_text', DataProcessingTask.status == 'running').first()
    if pending:
        return {'message': '任务已在运行中', 'task_id': pending.task_id}
    task_id = f"fill_ct_{__import__('uuid').uuid4().hex[:8]}"
    task = DataProcessingTask(task_id=task_id, category_id=None, mode='fill_content_text', status='pending', progress=0)
    db.add(task)
    db.commit()
    fill_content_text_task.delay()
    logger.bind(task_id=task_id).info("fill_content_text task dispatched")
    return {'message': 'fill_content_text 任务已派发', 'task_id': task_id}

@router.post('/backfill-attachment-content')
async def backfill_attachment_content(db: Session=Depends(get_db)):
    from app.models.tax_data import TaxDocument
    pending = db.query(DataProcessingTask).filter(DataProcessingTask.mode == 'backfill_attachment', DataProcessingTask.status == 'running').first()
    if pending:
        return {'message': '任务已在运行中', 'task_id': pending.task_id}
    count = db.query(TaxDocument).filter(TaxDocument.attachments.isnot(None), TaxDocument.content_markdown.notlike('%## 附件%')).count()
    task_id = f'backfill_att_{uuid.uuid4().hex[:8]}'
    task = DataProcessingTask(task_id=task_id, category_id=None, mode='backfill_attachment', status='pending', progress=0, total_count=count)
    db.add(task)
    db.commit()
    backfill_attachment_content_task.delay()
    logger.bind(task_id=task_id).info("backfill_attachment task dispatched", pending_count=count)
    return {'message': f'backfill_attachment 任务已派发，待处理文档约 {count} 条', 'task_id': task_id, 'pending_count': count}

class ReprocessCategoryRequest(BaseModel):
    category_ids: list[int] | None = None

@router.post('/reprocess-category')
async def reprocess_category(request: ReprocessCategoryRequest=Body(default=ReprocessCategoryRequest()), db: Session=Depends(get_db)):
    from app.models.tax_data import TaxDocument
    from app.services.tax_data_processor.category_processor import CategoryProcessor
    all_category_ids = [c['id'] for c in CategoryProcessor().get_all_categories()]
    target_ids = request.category_ids if request.category_ids else all_category_ids
    dispatched = []
    for cat_id in target_ids:
        doc_ids = [row[0] for row in db.query(TaxDocument.id).filter(TaxDocument.category_id == cat_id).all()]
        for doc_id in doc_ids:
            reprocess_from_local_task.delay(doc_id)
        dispatched.append({'category_id': cat_id, 'doc_count': len(doc_ids)})
    total = sum(d['doc_count'] for d in dispatched)
    logger.info("reprocess_category tasks dispatched", total_docs=total, categories=target_ids)
    return {'message': f'已派发 {total} 个本地重处理任务', 'categories': dispatched}

@router.post('/fix-json-null')
async def fix_json_null(db: Session=Depends(get_db)):
    fix_json_null_task.delay()
    return {'message': 'fix_json_null 任务已派发'}

@router.post('/fill-issuing-authority')
async def fill_issuing_authority(db: Session=Depends(get_db)):
    count = db.query(DataProcessingTask).filter(DataProcessingTask.mode == 'fill_issuing_authority', DataProcessingTask.status == 'running').count()
    if count:
        return {'message': '任务已在运行中'}
    fill_issuing_authority_task.delay()
    return {'message': 'fill_issuing_authority 任务已派发'}

@router.post('/fill-superseded-by')
async def fill_superseded_by(db: Session=Depends(get_db)):
    fill_superseded_by_task.delay()
    return {'message': 'fill_superseded_by 任务已派发'}

@router.post('/build-relations')
async def build_relations(db: Session=Depends(get_db)):
    build_relations_task.delay()
    return {'message': 'build_relations 任务已派发'}

@router.post('/backfill-media')
async def backfill_media(batch_size: int=50):
    backfill_media_task.delay(batch_size=batch_size)
    return {'message': 'backfill_media 任务已派发'}

@router.post('/cleanup')
async def cleanup_tasks(days: int=7, db: Session=Depends(get_db)):
    from datetime import timedelta
    cutoff = datetime.utcnow() - timedelta(days=days)
    deleted = db.query(DataProcessingTask).filter(DataProcessingTask.status.in_(['completed', 'failed', 'cancelled']), DataProcessingTask.updated_at < cutoff).delete(synchronize_session=False)
    zombie_cutoff = datetime.utcnow() - timedelta(hours=24)
    cancelled = db.query(DataProcessingTask).filter(DataProcessingTask.status == 'running', DataProcessingTask.started_at < zombie_cutoff).update({'status': 'cancelled', 'completed_at': datetime.utcnow()}, synchronize_session=False)
    db.commit()
    logger.info("tasks cleanup completed", deleted=deleted, cancelled_zombies=cancelled)
    return {'message': f'清理完成：删除 {deleted} 个旧任务，取消 {cancelled} 个僵尸任务', 'deleted': deleted, 'cancelled': cancelled}
