"""
자동 보고서 생성 — 주간/월간/분기 운영 보고서 자동 발송

기존 report.py를 확장하여 스케줄 기반 자동 생성 + 이메일 발송.

엔드포인트:
  GET  /api/auto-report/templates     — 보고서 템플릿 목록
  POST /api/auto-report/generate      — 보고서 즉시 생성
  GET  /api/auto-report/list          — 생성된 보고서 목록
  GET  /api/auto-report/{id}/download — 보고서 다운로드
  POST /api/auto-report/schedule      — 자동 발송 스케줄 설정
  GET  /api/auto-report/schedule      — 스케줄 목록
"""
from __future__ import annotations

import io
import json
import logging
from datetime import date, datetime, timedelta
from typing import Optional

from fastapi import APIRouter, Depends, HTTPException, Response
from pydantic import BaseModel, Field
from sqlalchemy import select, func
from sqlalchemy.ext.asyncio import AsyncSession

from core.auth import get_current_user, require_admin_role
from database import get_db
from models import User, SRRequest, SRStatus, ReportRecord, ReportSchedule  # 신규

logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/auto-report", tags=["Auto Report"])

TEMPLATES = {
    "weekly_ops":    {"name": "주간 운영 보고서", "period": "WEEKLY",  "format": ["excel", "pdf"]},
    "monthly_sla":   {"name": "월간 SLA 보고서",  "period": "MONTHLY", "format": ["excel", "pdf"]},
    "incident_rca":  {"name": "인시던트 분석",    "period": "MONTHLY", "format": ["pdf"]},
    "capacity_plan": {"name": "용량 계획 보고서",  "period": "QUARTERLY","format": ["excel"]},
}


class GenerateRequest(BaseModel):
    template: str = Field(..., description="weekly_ops | monthly_sla | incident_rca | capacity_plan")
    period_start: Optional[str] = None  # YYYY-MM-DD
    period_end: Optional[str] = None
    format: str = Field("excel", pattern="^(excel|pdf)$")
    send_email: bool = False
    email: Optional[str] = None

class ScheduleCreate(BaseModel):
    template: str
    cron: str = Field(..., description="cron 표현식 (예: 0 9 * * 1 = 매주 월요일 9시)")
    email: str
    format: str = "excel"


async def _collect_report_data(template: str, start: date, end: date, db: AsyncSession) -> dict:
    """보고서 데이터 수집."""
    total_r = await db.execute(
        select(func.count(SRRequest.id)).where(
            SRRequest.created_at >= start, SRRequest.created_at <= end
        )
    )
    done_r = await db.execute(
        select(func.count(SRRequest.id)).where(
            SRRequest.status == SRStatus.DONE,
            SRRequest.updated_at >= start, SRRequest.updated_at <= end,
        )
    )
    open_r = await db.execute(
        select(func.count(SRRequest.id)).where(SRRequest.status.in_([SRStatus.OPEN, SRStatus.IN_PROGRESS]))
    )
    mttr_r = await db.execute(
        select(func.avg(
            func.extract('epoch', SRRequest.updated_at - SRRequest.created_at) / 3600
        )).where(SRRequest.status == SRStatus.DONE, SRRequest.updated_at >= start, SRRequest.updated_at <= end)
    )

    total = total_r.scalar() or 0
    done = done_r.scalar() or 0
    return {
        "period": {"start": start.isoformat(), "end": end.isoformat()},
        "sr_total": total, "sr_done": done, "sr_open": open_r.scalar() or 0,
        "completion_rate": round(done / total * 100, 1) if total else 0,
        "mttr_hours": round(mttr_r.scalar() or 0, 1),
    }


def _build_excel(data: dict, template: str) -> bytes:
    """Excel 보고서 생성 (openpyxl)."""
    try:
        import openpyxl
        from openpyxl.styles import Font, PatternFill, Alignment

        wb = openpyxl.Workbook()
        ws = wb.active
        ws.title = TEMPLATES.get(template, {}).get("name", "보고서")

        # 헤더
        ws["A1"] = TEMPLATES.get(template, {}).get("name", "운영 보고서")
        ws["A1"].font = Font(bold=True, size=14)
        ws["A2"] = f"기간: {data['period']['start']} ~ {data['period']['end']}"

        ws["A4"] = "지표"; ws["B4"] = "값"
        ws["A4"].font = Font(bold=True)
        ws["B4"].font = Font(bold=True)

        rows = [
            ("신규 SR", data["sr_total"]),
            ("완료 SR", data["sr_done"]),
            ("미처리 SR", data["sr_open"]),
            ("완료율 (%)", data["completion_rate"]),
            ("평균 처리 시간 (시간)", data["mttr_hours"]),
        ]
        for i, (label, value) in enumerate(rows, start=5):
            ws[f"A{i}"] = label
            ws[f"B{i}"] = value

        ws["A4"].fill = PatternFill(start_color="003366", end_color="003366", fill_type="solid")
        ws["A4"].font = Font(bold=True, color="FFFFFF")
        ws["B4"].fill = PatternFill(start_color="003366", end_color="003366", fill_type="solid")
        ws["B4"].font = Font(bold=True, color="FFFFFF")
        ws.column_dimensions["A"].width = 25
        ws.column_dimensions["B"].width = 15

        output = io.BytesIO()
        wb.save(output)
        return output.getvalue()
    except ImportError:
        # openpyxl 없으면 CSV 대체
        lines = [f"{k},{v}" for k, v in [("지표", "값")] + [(str(k), str(v)) for k, v in [
            ("신규 SR", data["sr_total"]), ("완료율", data["completion_rate"])
        ]]]
        return "\n".join(lines).encode('utf-8-sig')


@router.get("/templates")
async def list_templates():
    return [{"code": k, **v} for k, v in TEMPLATES.items()]


@router.post("/generate")
async def generate_report(
    req: GenerateRequest, db: AsyncSession = Depends(get_db),
    user: User = Depends(get_current_user),
):
    if req.template not in TEMPLATES:
        raise HTTPException(400, f"알 수 없는 템플릿: {req.template}")

    today = date.today()
    if req.period_start and req.period_end:
        start = date.fromisoformat(req.period_start)
        end = date.fromisoformat(req.period_end)
    else:
        period = TEMPLATES[req.template]["period"]
        if period == "WEEKLY":
            start = today - timedelta(days=7); end = today
        elif period == "QUARTERLY":
            q_start = date(today.year, ((today.month - 1) // 3) * 3 + 1, 1)
            start = q_start; end = today
        else:  # MONTHLY
            start = today.replace(day=1); end = today

    data = await _collect_report_data(req.template, start, end, db)
    excel_bytes = _build_excel(data, req.template)

    record = ReportRecord(
        tenant_id=user.tenant_id, template=req.template,
        period_start=start, period_end=end,
        format=req.format, file_size=len(excel_bytes),
        status="DONE", generated_by=user.id, created_at=datetime.utcnow()
    )
    db.add(record)
    await db.commit()
    await db.refresh(record)

    return {
        "ok": True, "report_id": record.id,
        "template": req.template, "period": data["period"],
        "data_summary": data,
    }


@router.get("/{report_id}/download")
async def download_report(
    report_id: int, db: AsyncSession = Depends(get_db),
    user: User = Depends(get_current_user),
):
    row = await db.execute(
        select(ReportRecord).where(ReportRecord.id == report_id, ReportRecord.tenant_id == user.tenant_id)
    )
    record = row.scalar_one_or_none()
    if not record: raise HTTPException(404, "보고서 없음")

    data = await _collect_report_data(record.template, record.period_start, record.period_end, db)
    excel_bytes = _build_excel(data, record.template)
    filename = f"report_{record.template}_{record.period_start}.xlsx"
    return Response(
        content=excel_bytes,
        media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
        headers={"Content-Disposition": f"attachment; filename={filename}"},
    )


@router.get("/list")
async def list_reports(db: AsyncSession = Depends(get_db), user: User = Depends(get_current_user)):
    rows = await db.execute(
        select(ReportRecord).where(ReportRecord.tenant_id == user.tenant_id)
        .order_by(ReportRecord.created_at.desc()).limit(50)
    )
    records = rows.scalars().all()
    return [
        {"id": r.id, "template": r.template, "period": f"{r.period_start}~{r.period_end}",
         "format": r.format, "status": r.status, "created_at": r.created_at}
        for r in records
    ]
