import logging
import json
from datetime import datetime
from typing import Any, Dict, List, Optional

from fastapi import APIRouter, HTTPException, Query, Request
from pydantic import BaseModel, Field

from app.modules.orders.backend.economic_export import ordre_economic_export_service
from app.modules.orders.backend.service import aggregate_order_lines

logger = logging.getLogger(__name__)
router = APIRouter()


class OrdreLineInput(BaseModel):
    line_key: str
    source_type: str
    source_id: int
    description: str
    quantity: float = Field(gt=0)
    unit_price: float = Field(ge=0)
    discount_percentage: float = Field(default=0, ge=0, le=100)
    unit: Optional[str] = None
    product_id: Optional[int] = None
    selected: bool = True


class OrdreExportRequest(BaseModel):
    customer_id: int
    lines: List[OrdreLineInput]
    notes: Optional[str] = None
    layout_number: Optional[int] = None
    draft_id: Optional[int] = None


class OrdreDraftUpsertRequest(BaseModel):
    title: str = Field(min_length=1, max_length=120)
    customer_id: Optional[int] = None
    lines: List[Dict[str, Any]] = Field(default_factory=list)
    notes: Optional[str] = None
    layout_number: Optional[int] = None


def _safe_json_field(value: Any) -> Any:
    if value is None:
        return None
    if isinstance(value, (dict, list)):
        return value
    if isinstance(value, str):
        try:
            return json.loads(value)
        except json.JSONDecodeError:
            return value
    return value


def _get_user_id_from_request(http_request: Request) -> Optional[int]:
    state_user_id = getattr(http_request.state, "user_id", None)
    if state_user_id is None:
        return None
    try:
        return int(state_user_id)
    except (TypeError, ValueError):
        return None


@router.get("/ordre/aggregate")
async def get_ordre_aggregate(
    customer_id: Optional[int] = Query(None),
    sag_id: Optional[int] = Query(None),
    q: Optional[str] = Query(None),
):
    """Aggregate global ordre lines from subscriptions, hardware and sales."""
    try:
        return aggregate_order_lines(customer_id=customer_id, sag_id=sag_id, q=q)
    except Exception as e:
        logger.error("❌ Error aggregating ordre lines: %s", e, exc_info=True)
        raise HTTPException(status_code=500, detail="Failed to aggregate ordre lines")


@router.get("/ordre/config")
async def get_ordre_config():
    """Return ordre module safety config for frontend banner."""
    return {
        "economic_read_only": ordre_economic_export_service.read_only,
        "economic_dry_run": ordre_economic_export_service.dry_run,
        "default_layout": ordre_economic_export_service.default_layout,
        "default_product": ordre_economic_export_service.default_product,
    }


@router.post("/ordre/export")
async def export_ordre(request: OrdreExportRequest, http_request: Request):
    """Export selected ordre lines to e-conomic draft order."""
    try:
        user_id = _get_user_id_from_request(http_request)

        line_payload = [line.model_dump() for line in request.lines]
        export_result = await ordre_economic_export_service.export_order(
            customer_id=request.customer_id,
            lines=line_payload,
            notes=request.notes,
            layout_number=request.layout_number,
            user_id=user_id,
        )

        exported_line_keys = [line.get("line_key") for line in line_payload if line.get("line_key")]
        export_result["exported_line_keys"] = exported_line_keys

        if request.draft_id:
            from app.core.database import execute_query_single, execute_query

            existing = execute_query_single("SELECT export_status_json FROM ordre_drafts WHERE id = %s", (request.draft_id,))
            existing_status = _safe_json_field((existing or {}).get("export_status_json")) or {}
            if not isinstance(existing_status, dict):
                existing_status = {}

            line_status = "dry-run" if export_result.get("dry_run") else "exported"
            for line_key in exported_line_keys:
                existing_status[line_key] = {
                    "status": line_status,
                    "timestamp": datetime.utcnow().isoformat(),
                }

            execute_query(
                """
                UPDATE ordre_drafts
                SET export_status_json = %s::jsonb,
                    last_exported_at = CURRENT_TIMESTAMP,
                    updated_at = CURRENT_TIMESTAMP
                WHERE id = %s
                """,
                (json.dumps(existing_status, ensure_ascii=False), request.draft_id),
            )

        return export_result
    except HTTPException:
        raise
    except Exception as e:
        logger.error("❌ Error exporting ordre to e-conomic: %s", e, exc_info=True)
        raise HTTPException(status_code=500, detail="Failed to export ordre")


@router.get("/ordre/drafts")
async def list_ordre_drafts(
    http_request: Request, 
    limit: int = Query(25, ge=1, le=100)
):
    """List all ordre drafts (no user filtering)."""
    try:
        query = """
            SELECT id, title, customer_id, notes, layout_number, created_by_user_id,
                   created_at, updated_at, last_exported_at
            FROM ordre_drafts
            ORDER BY updated_at DESC, id DESC
            LIMIT %s
        """
        params = (limit,)

        from app.core.database import execute_query
        return execute_query(query, params) or []
    except Exception as e:
        logger.error("❌ Error listing ordre drafts: %s", e, exc_info=True)
        raise HTTPException(status_code=500, detail="Failed to list ordre drafts")


@router.get("/ordre/drafts/{draft_id}")
async def get_ordre_draft(draft_id: int, http_request: Request):
    """Get single ordre draft with lines payload (no user filtering)."""
    try:
        query = "SELECT * FROM ordre_drafts WHERE id = %s LIMIT 1"
        params = (draft_id,)

        from app.core.database import execute_query_single
        draft = execute_query_single(query, params)
        if not draft:
            raise HTTPException(status_code=404, detail="Draft not found")

        draft["lines_json"] = _safe_json_field(draft.get("lines_json")) or []
        draft["export_status_json"] = _safe_json_field(draft.get("export_status_json")) or {}
        return draft
    except HTTPException:
        raise
    except Exception as e:
        logger.error("❌ Error fetching ordre draft: %s", e, exc_info=True)
        raise HTTPException(status_code=500, detail="Failed to fetch ordre draft")


@router.post("/ordre/drafts")
async def create_ordre_draft(request: OrdreDraftUpsertRequest, http_request: Request):
    """Create a new ordre draft."""
    try:
        user_id = _get_user_id_from_request(http_request)
        from app.core.database import execute_query

        query = """
            INSERT INTO ordre_drafts (
                title,
                customer_id,
                lines_json,
                notes,
                layout_number,
                created_by_user_id,
                export_status_json,
                updated_at
            ) VALUES (%s, %s, %s::jsonb, %s, %s, %s, %s::jsonb, CURRENT_TIMESTAMP)
            RETURNING *
        """
        params = (
            request.title,
            request.customer_id,
            json.dumps(request.lines, ensure_ascii=False),
            request.notes,
            request.layout_number,
            user_id,
            json.dumps({}, ensure_ascii=False),
        )
        result = execute_query(query, params)
        return result[0]
    except Exception as e:
        logger.error("❌ Error creating ordre draft: %s", e, exc_info=True)
        raise HTTPException(status_code=500, detail="Failed to create ordre draft")


@router.patch("/ordre/drafts/{draft_id}")
async def update_ordre_draft(draft_id: int, request: OrdreDraftUpsertRequest, http_request: Request):
    """Update existing ordre draft."""
    try:
        from app.core.database import execute_query

        query = """
            UPDATE ordre_drafts
            SET title = %s,
                customer_id = %s,
                lines_json = %s::jsonb,
                notes = %s,
                layout_number = %s,
                updated_at = CURRENT_TIMESTAMP
            WHERE id = %s
            RETURNING *
        """
        params = (
            request.title,
            request.customer_id,
            json.dumps(request.lines, ensure_ascii=False),
            request.notes,
            request.layout_number,
            draft_id,
        )

        result = execute_query(query, params)
        if not result:
            raise HTTPException(status_code=404, detail="Draft not found")
        return result[0]
    except HTTPException:
        raise
    except Exception as e:
        logger.error("❌ Error updating ordre draft: %s", e, exc_info=True)
        raise HTTPException(status_code=500, detail="Failed to update ordre draft")


@router.delete("/ordre/drafts/{draft_id}")
async def delete_ordre_draft(draft_id: int, http_request: Request):
    """Delete ordre draft."""
    try:
        from app.core.database import execute_query

        query = "DELETE FROM ordre_drafts WHERE id = %s RETURNING id"
        params = (draft_id,)

        result = execute_query(query, params)
        if not result:
            raise HTTPException(status_code=404, detail="Draft not found")
        return {"status": "deleted", "id": draft_id}
    except HTTPException:
        raise
    except Exception as e:
        logger.error("❌ Error deleting ordre draft: %s", e, exc_info=True)
        raise HTTPException(status_code=500, detail="Failed to delete ordre draft")
