"""
KaplanOS - Tüm modül endpoint'leri
projects, crm, transactions, notes, calendar, goals, dashboard
"""
from typing import List, Optional
from decimal import Decimal
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from sqlalchemy import and_, func, extract
from datetime import date, datetime

from app.core.dependencies import get_db, get_current_active_user
from app.models.user import User
from app.models.task import Task
from app.models.project import Project
from app.models import Customer, Transaction, Note, CalendarEvent, Goal
from app.schemas import (
    ProjectCreate, ProjectUpdate, ProjectResponse,
    CustomerCreate, CustomerUpdate, CustomerStatusUpdate, CustomerResponse,
    TransactionCreate, TransactionUpdate, TransactionResponse, FinanceSummary,
    NoteCreate, NoteUpdate, NoteResponse,
    CalendarEventCreate, CalendarEventUpdate, CalendarEventResponse,
    GoalCreate, GoalUpdate, GoalProgressUpdate, GoalResponse,
    DashboardStats, TaskResponse, MessageResponse,
)


# ─── PROJELER ─────────────────────────────────────────────────────────────────
projects_router = APIRouter(prefix="/projects", tags=["Projeler"])


def get_project_or_404(project_id: int, user_id: int, db: Session) -> Project:
    p = db.query(Project).filter(
        Project.id == project_id, Project.user_id == user_id, Project.is_deleted == False
    ).first()
    if not p:
        raise HTTPException(status_code=404, detail="Proje bulunamadı.")
    return p


@projects_router.get("", response_model=List[ProjectResponse])
def list_projects(
    status: Optional[str] = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    q = db.query(Project).filter(Project.user_id == current_user.id, Project.is_deleted == False)
    if status:
        q = q.filter(Project.status == status)
    projects = q.order_by(Project.created_at.desc()).all()
    for p in projects:
        p.task_count = db.query(Task).filter(Task.project_id == p.id, Task.is_deleted == False).count()
    return projects


@projects_router.post("", response_model=ProjectResponse, status_code=201)
def create_project(project_in: ProjectCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    project = Project(**project_in.model_dump(), user_id=current_user.id)
    db.add(project)
    db.commit()
    db.refresh(project)
    return project


@projects_router.get("/{project_id}", response_model=ProjectResponse)
def get_project(project_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    p = get_project_or_404(project_id, current_user.id, db)
    p.task_count = db.query(Task).filter(Task.project_id == p.id, Task.is_deleted == False).count()
    return p


@projects_router.put("/{project_id}", response_model=ProjectResponse)
def update_project(project_id: int, project_in: ProjectUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    project = get_project_or_404(project_id, current_user.id, db)
    for field, value in project_in.model_dump(exclude_unset=True).items():
        setattr(project, field, value)
    db.commit()
    db.refresh(project)
    return project


@projects_router.delete("/{project_id}", response_model=MessageResponse)
def delete_project(project_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    project = get_project_or_404(project_id, current_user.id, db)
    project.is_deleted = True
    db.commit()
    return MessageResponse(message="Proje silindi.")


@projects_router.patch("/{project_id}/progress", response_model=ProjectResponse)
def update_project_progress(project_id: int, progress: int = Query(..., ge=0, le=100), db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    project = get_project_or_404(project_id, current_user.id, db)
    project.progress_pct = progress
    db.commit()
    db.refresh(project)
    return project


@projects_router.get("/{project_id}/tasks", response_model=List[TaskResponse])
def get_project_tasks(project_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    get_project_or_404(project_id, current_user.id, db)
    return db.query(Task).filter(Task.project_id == project_id, Task.is_deleted == False).all()


# ─── CRM ──────────────────────────────────────────────────────────────────────
crm_router = APIRouter(prefix="/customers", tags=["CRM"])


def get_customer_or_404(customer_id: int, user_id: int, db: Session) -> Customer:
    c = db.query(Customer).filter(
        Customer.id == customer_id, Customer.user_id == user_id, Customer.is_deleted == False
    ).first()
    if not c:
        raise HTTPException(status_code=404, detail="Müşteri bulunamadı.")
    return c


@crm_router.get("", response_model=List[CustomerResponse])
def list_customers(
    status: Optional[str] = None,
    search: Optional[str] = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    q = db.query(Customer).filter(Customer.user_id == current_user.id, Customer.is_deleted == False)
    if status:
        q = q.filter(Customer.status == status)
    if search:
        from sqlalchemy import or_
        q = q.filter(or_(Customer.company_name.ilike(f"%{search}%"), Customer.contact_person.ilike(f"%{search}%")))
    return q.order_by(Customer.created_at.desc()).all()


@crm_router.post("", response_model=CustomerResponse, status_code=201)
def create_customer(customer_in: CustomerCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    customer = Customer(**customer_in.model_dump(), user_id=current_user.id)
    db.add(customer)
    db.commit()
    db.refresh(customer)
    return customer


@crm_router.get("/{customer_id}", response_model=CustomerResponse)
def get_customer(customer_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    return get_customer_or_404(customer_id, current_user.id, db)


@crm_router.put("/{customer_id}", response_model=CustomerResponse)
def update_customer(customer_id: int, customer_in: CustomerUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    customer = get_customer_or_404(customer_id, current_user.id, db)
    for field, value in customer_in.model_dump(exclude_unset=True).items():
        setattr(customer, field, value)
    db.commit()
    db.refresh(customer)
    return customer


@crm_router.delete("/{customer_id}", response_model=MessageResponse)
def delete_customer(customer_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    customer = get_customer_or_404(customer_id, current_user.id, db)
    customer.is_deleted = True
    db.commit()
    return MessageResponse(message="Müşteri silindi.")


@crm_router.patch("/{customer_id}/status", response_model=CustomerResponse)
def update_customer_status(customer_id: int, status_in: CustomerStatusUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    customer = get_customer_or_404(customer_id, current_user.id, db)
    customer.status = status_in.status
    db.commit()
    db.refresh(customer)
    return customer


# ─── FİNANS ───────────────────────────────────────────────────────────────────
finance_router = APIRouter(prefix="/transactions", tags=["Finans"])


def get_transaction_or_404(tx_id: int, user_id: int, db: Session) -> Transaction:
    t = db.query(Transaction).filter(
        Transaction.id == tx_id, Transaction.user_id == user_id, Transaction.is_deleted == False
    ).first()
    if not t:
        raise HTTPException(status_code=404, detail="İşlem bulunamadı.")
    return t


@finance_router.get("", response_model=List[TransactionResponse])
def list_transactions(
    type: Optional[str] = None,
    category: Optional[str] = None,
    start_date: Optional[date] = None,
    end_date: Optional[date] = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    q = db.query(Transaction).filter(Transaction.user_id == current_user.id, Transaction.is_deleted == False)
    if type:
        q = q.filter(Transaction.type == type)
    if category:
        q = q.filter(Transaction.category == category)
    if start_date:
        q = q.filter(Transaction.date >= start_date)
    if end_date:
        q = q.filter(Transaction.date <= end_date)
    return q.order_by(Transaction.date.desc()).all()


@finance_router.post("", response_model=TransactionResponse, status_code=201)
def create_transaction(tx_in: TransactionCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    tx = Transaction(**tx_in.model_dump(), user_id=current_user.id)
    db.add(tx)
    db.commit()
    db.refresh(tx)
    return tx


@finance_router.get("/summary", response_model=FinanceSummary)
def get_finance_summary(
    year: Optional[int] = None,
    month: Optional[int] = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    q = db.query(Transaction).filter(Transaction.user_id == current_user.id, Transaction.is_deleted == False)
    if year:
        q = q.filter(extract("year", Transaction.date) == year)
    if month:
        q = q.filter(extract("month", Transaction.date) == month)

    transactions = q.all()
    income = sum(float(t.amount) for t in transactions if t.type == "gelir")
    expense = sum(float(t.amount) for t in transactions if t.type == "gider")

    return FinanceSummary(
        total_income=Decimal(str(income)),
        total_expense=Decimal(str(expense)),
        profit=Decimal(str(income - expense)),
        year=year,
        month=month,
    )


@finance_router.get("/{tx_id}", response_model=TransactionResponse)
def get_transaction(tx_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    return get_transaction_or_404(tx_id, current_user.id, db)


@finance_router.put("/{tx_id}", response_model=TransactionResponse)
def update_transaction(tx_id: int, tx_in: TransactionUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    tx = get_transaction_or_404(tx_id, current_user.id, db)
    for field, value in tx_in.model_dump(exclude_unset=True).items():
        setattr(tx, field, value)
    db.commit()
    db.refresh(tx)
    return tx


@finance_router.delete("/{tx_id}", response_model=MessageResponse)
def delete_transaction(tx_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    tx = get_transaction_or_404(tx_id, current_user.id, db)
    tx.is_deleted = True
    db.commit()
    return MessageResponse(message="İşlem silindi.")


# ─── NOTLAR ───────────────────────────────────────────────────────────────────
notes_router = APIRouter(prefix="/notes", tags=["Notlar"])


def get_note_or_404(note_id: int, user_id: int, db: Session) -> Note:
    n = db.query(Note).filter(Note.id == note_id, Note.user_id == user_id, Note.is_deleted == False).first()
    if not n:
        raise HTTPException(status_code=404, detail="Not bulunamadı.")
    return n


@notes_router.get("", response_model=List[NoteResponse])
def list_notes(
    category: Optional[str] = None,
    tag: Optional[str] = None,
    favorite: Optional[bool] = None,
    search: Optional[str] = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    q = db.query(Note).filter(Note.user_id == current_user.id, Note.is_deleted == False)
    if category:
        q = q.filter(Note.category == category)
    if favorite is not None:
        q = q.filter(Note.is_favorite == favorite)
    if search:
        from sqlalchemy import or_
        q = q.filter(or_(Note.title.ilike(f"%{search}%"), Note.content.ilike(f"%{search}%")))
    return q.order_by(Note.is_favorite.desc(), Note.updated_at.desc()).all()


@notes_router.post("", response_model=NoteResponse, status_code=201)
def create_note(note_in: NoteCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    note = Note(**note_in.model_dump(), user_id=current_user.id)
    db.add(note)
    db.commit()
    db.refresh(note)
    return note


@notes_router.get("/{note_id}", response_model=NoteResponse)
def get_note(note_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    return get_note_or_404(note_id, current_user.id, db)


@notes_router.put("/{note_id}", response_model=NoteResponse)
def update_note(note_id: int, note_in: NoteUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    note = get_note_or_404(note_id, current_user.id, db)
    for field, value in note_in.model_dump(exclude_unset=True).items():
        setattr(note, field, value)
    db.commit()
    db.refresh(note)
    return note


@notes_router.delete("/{note_id}", response_model=MessageResponse)
def delete_note(note_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    note = get_note_or_404(note_id, current_user.id, db)
    note.is_deleted = True
    db.commit()
    return MessageResponse(message="Not silindi.")


@notes_router.patch("/{note_id}/favorite", response_model=NoteResponse)
def toggle_favorite(note_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    note = get_note_or_404(note_id, current_user.id, db)
    note.is_favorite = not note.is_favorite
    db.commit()
    db.refresh(note)
    return note


# ─── TAKVİM ───────────────────────────────────────────────────────────────────
calendar_router = APIRouter(prefix="/calendar", tags=["Takvim"])


def get_event_or_404(event_id: int, user_id: int, db: Session) -> CalendarEvent:
    e = db.query(CalendarEvent).filter(CalendarEvent.id == event_id, CalendarEvent.user_id == user_id, CalendarEvent.is_deleted == False).first()
    if not e:
        raise HTTPException(status_code=404, detail="Etkinlik bulunamadı.")
    return e


@calendar_router.get("", response_model=List[CalendarEventResponse])
def list_events(
    start: datetime = Query(...),
    end: datetime = Query(...),
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    return db.query(CalendarEvent).filter(
        CalendarEvent.user_id == current_user.id,
        CalendarEvent.is_deleted == False,
        CalendarEvent.start_datetime >= start,
        CalendarEvent.start_datetime <= end,
    ).all()


@calendar_router.post("", response_model=CalendarEventResponse, status_code=201)
def create_event(event_in: CalendarEventCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    event = CalendarEvent(**event_in.model_dump(), user_id=current_user.id)
    db.add(event)
    db.commit()
    db.refresh(event)
    return event


@calendar_router.put("/{event_id}", response_model=CalendarEventResponse)
def update_event(event_id: int, event_in: CalendarEventUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    event = get_event_or_404(event_id, current_user.id, db)
    for field, value in event_in.model_dump(exclude_unset=True).items():
        setattr(event, field, value)
    db.commit()
    db.refresh(event)
    return event


@calendar_router.delete("/{event_id}", response_model=MessageResponse)
def delete_event(event_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    event = get_event_or_404(event_id, current_user.id, db)
    event.is_deleted = True
    db.commit()
    return MessageResponse(message="Etkinlik silindi.")


# ─── HEDEFLER ─────────────────────────────────────────────────────────────────
goals_router = APIRouter(prefix="/goals", tags=["Hedefler"])


def get_goal_or_404(goal_id: int, user_id: int, db: Session) -> Goal:
    g = db.query(Goal).filter(Goal.id == goal_id, Goal.user_id == user_id, Goal.is_deleted == False).first()
    if not g:
        raise HTTPException(status_code=404, detail="Hedef bulunamadı.")
    return g


@goals_router.get("", response_model=List[GoalResponse])
def list_goals(
    status: Optional[str] = None,
    category: Optional[str] = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    q = db.query(Goal).filter(Goal.user_id == current_user.id, Goal.is_deleted == False)
    if status:
        q = q.filter(Goal.status == status)
    if category:
        q = q.filter(Goal.category == category)
    goals = q.order_by(Goal.created_at.desc()).all()
    for g in goals:
        g.__dict__['progress_pct'] = g.progress_pct
    return goals


@goals_router.post("", response_model=GoalResponse, status_code=201)
def create_goal(goal_in: GoalCreate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    goal = Goal(**goal_in.model_dump(), user_id=current_user.id)
    db.add(goal)
    db.commit()
    db.refresh(goal)
    return goal


@goals_router.put("/{goal_id}", response_model=GoalResponse)
def update_goal(goal_id: int, goal_in: GoalUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    goal = get_goal_or_404(goal_id, current_user.id, db)
    for field, value in goal_in.model_dump(exclude_unset=True).items():
        setattr(goal, field, value)
    db.commit()
    db.refresh(goal)
    return goal


@goals_router.patch("/{goal_id}/progress", response_model=GoalResponse)
def update_goal_progress(goal_id: int, progress_in: GoalProgressUpdate, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    goal = get_goal_or_404(goal_id, current_user.id, db)
    goal.current_value = progress_in.current_value
    if float(goal.current_value) >= float(goal.target_value):
        goal.status = "tamamlandi"
    db.commit()
    db.refresh(goal)
    return goal


@goals_router.delete("/{goal_id}", response_model=MessageResponse)
def delete_goal(goal_id: int, db: Session = Depends(get_db), current_user: User = Depends(get_current_active_user)):
    goal = get_goal_or_404(goal_id, current_user.id, db)
    goal.is_deleted = True
    db.commit()
    return MessageResponse(message="Hedef silindi.")


# ─── DASHBOARD ────────────────────────────────────────────────────────────────
dashboard_router = APIRouter(prefix="/dashboard", tags=["Dashboard"])


@dashboard_router.get("/stats", response_model=DashboardStats)
def get_dashboard_stats(
    db: Session = Depends(get_db),
    current_user: User = Depends(get_current_active_user),
):
    """Dashboard için tek sorguda tüm istatistikler."""
    from datetime import date as date_type
    today = date_type.today()
    current_month = today.month
    current_year = today.year

    uid = current_user.id

    total_tasks = db.query(Task).filter(Task.user_id == uid, Task.is_deleted == False).count()

    completed_today = db.query(Task).filter(
        Task.user_id == uid,
        Task.status == "tamamlandi",
        Task.is_deleted == False,
        func.date(Task.updated_at) == today,
    ).count()

    active_projects = db.query(Project).filter(
        Project.user_id == uid,
        Project.status == "aktif",
        Project.is_deleted == False,
    ).count()

    monthly_txs = db.query(Transaction).filter(
        Transaction.user_id == uid,
        Transaction.is_deleted == False,
        extract("year", Transaction.date) == current_year,
        extract("month", Transaction.date) == current_month,
    ).all()

    monthly_income = sum(float(t.amount) for t in monthly_txs if t.type == "gelir")
    monthly_expense = sum(float(t.amount) for t in monthly_txs if t.type == "gider")

    total_customers = db.query(Customer).filter(
        Customer.user_id == uid, Customer.is_deleted == False
    ).count()

    active_goals = db.query(Goal).filter(
        Goal.user_id == uid, Goal.status == "aktif", Goal.is_deleted == False
    ).count()

    upcoming_tasks = db.query(Task).filter(
        Task.user_id == uid,
        Task.is_deleted == False,
        Task.status.in_(["bekliyor", "devam_ediyor"]),
        Task.due_date >= today,
    ).order_by(Task.due_date.asc()).limit(5).all()

    recent_transactions = db.query(Transaction).filter(
        Transaction.user_id == uid, Transaction.is_deleted == False
    ).order_by(Transaction.date.desc()).limit(5).all()

    return DashboardStats(
        total_tasks=total_tasks,
        completed_tasks_today=completed_today,
        active_projects=active_projects,
        monthly_income=Decimal(str(monthly_income)),
        monthly_expense=Decimal(str(monthly_expense)),
        monthly_profit=Decimal(str(monthly_income - monthly_expense)),
        total_customers=total_customers,
        active_goals=active_goals,
        upcoming_tasks=upcoming_tasks,
        recent_transactions=recent_transactions,
    )
