import { NextResponse } from 'next/server';
import { getServerSession } from 'next-auth';
import { authOptions } from "@/lib/auth";
import { prisma } from '@/lib/prisma';

// ── Field registry ─────────────────────────────────────────────────────────
export type ExportFieldKey =
    | 'week'
    | 'weekGoal'
    | 'completedDate'
    | 'scheduledDate'
    | 'createdDate'
    | 'project'
    | 'list'
    | 'priority'
    | 'url'
    | 'notes'
    | 'description'
    | 'delegatedTo'
    | 'delegationNote'
    | 'startTime'
    | 'kanbanStage';

export const EXPORT_FIELDS: {
    key: ExportFieldKey;
    labelDe: string;
    labelEn: string;
    defaultOn: boolean;
    csvOnly?: boolean; // not a table column, only used as a section in PDF/CSV
}[] = [
    { key: 'week',           labelDe: 'Kalenderwoche',      labelEn: 'Calendar week',    defaultOn: true,  csvOnly: true },
    { key: 'weekGoal',       labelDe: 'Wochenziel',         labelEn: 'Goal of the week', defaultOn: true,  csvOnly: true },
    { key: 'completedDate',  labelDe: 'Erledigt am',        labelEn: 'Completed',        defaultOn: true  },
    { key: 'scheduledDate',  labelDe: 'Geplant für',        labelEn: 'Scheduled for',    defaultOn: true  },
    { key: 'createdDate',    labelDe: 'Erstellt am',        labelEn: 'Created',          defaultOn: false },
    { key: 'project',        labelDe: 'Projekt',            labelEn: 'Project',          defaultOn: true  },
    { key: 'list',           labelDe: 'Liste',              labelEn: 'List',             defaultOn: true  },
    { key: 'priority',       labelDe: 'Priorität',          labelEn: 'Priority',         defaultOn: true  },
    { key: 'url',            labelDe: 'Link / URL',         labelEn: 'Link / URL',       defaultOn: false },
    { key: 'notes',          labelDe: 'Notiz',              labelEn: 'Notes',            defaultOn: false },
    { key: 'description',    labelDe: 'Beschreibung',       labelEn: 'Description',      defaultOn: false },
    { key: 'delegatedTo',    labelDe: 'Delegiert an',       labelEn: 'Delegated to',     defaultOn: false },
    { key: 'delegationNote', labelDe: 'Delegationsnotiz',   labelEn: 'Delegation note',  defaultOn: false },
    { key: 'startTime',      labelDe: 'Uhrzeit',            labelEn: 'Start time',       defaultOn: false },
    { key: 'kanbanStage',    labelDe: 'Kanban-Stage',       labelEn: 'Kanban stage',     defaultOn: false },
];

// ── Shared helpers (also used by export-pdf route) ─────────────────────────

export function isoWeek(date: Date): string {
    const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate()));
    const dayNum = d.getUTCDay() || 7;
    d.setUTCDate(d.getUTCDate() + 4 - dayNum);
    const yearStart = new Date(Date.UTC(d.getUTCFullYear(), 0, 1));
    const weekNo = Math.ceil((((d.getTime() - yearStart.getTime()) / 86400000) + 1) / 7);
    return `${d.getUTCFullYear()}-W${String(weekNo).padStart(2, '0')}`;
}

export function weekMondaySunday(weekKey: string): { mon: Date; sun: Date } {
    const [year, w] = weekKey.split('-W');
    const d = new Date(Date.UTC(parseInt(year), 0, 1));
    d.setUTCDate(d.getUTCDate() + (parseInt(w) - 1) * 7 - (d.getUTCDay() || 7) + 1);
    const sun = new Date(d); sun.setUTCDate(d.getUTCDate() + 6);
    return { mon: d, sun };
}

export function weekLabel(weekKey: string, de: boolean): string {
    const [, w] = weekKey.split('-W');
    const year = weekKey.split('-W')[0];
    const { mon, sun } = weekMondaySunday(weekKey);
    const fmt = (x: Date) => x.toLocaleDateString(de ? 'de-DE' : 'en-GB', { day: '2-digit', month: 'short', timeZone: 'UTC' });
    return de
        ? `KW ${w} — ${year}  (${fmt(mon)} – ${fmt(sun)})`
        : `Week ${w} — ${year}  (${fmt(mon)} – ${fmt(sun)})`;
}

export function fmtDate(d: Date | null | undefined, de: boolean): string {
    if (!d) return '';
    return de
        ? d.toLocaleDateString('de-DE', { day: '2-digit', month: '2-digit', year: 'numeric' })
        : d.toLocaleDateString('en-GB', { day: '2-digit', month: 'short', year: 'numeric' });
}

export function priorityLabel(task: any, de: boolean): string {
    if (task.urgency != null && task.importance != null) {
        if (task.urgency && task.importance)  return de ? 'Sofort erledigen' : 'Do now';
        if (!task.urgency && task.importance) return de ? 'Planen'           : 'Schedule';
        if (task.urgency && !task.importance) return de ? 'Delegieren'       : 'Delegate';
        return de ? 'Eliminieren' : 'Eliminate';
    }
    if (task.priority) return task.priority;
    return '';
}

export function priorityColor(task: any): string {
    if (task.urgency != null && task.importance != null) {
        if (task.urgency && task.importance)  return '#ef4444';
        if (!task.urgency && task.importance) return '#3b82f6';
        if (task.urgency && !task.importance) return '#f97316';
        return '#9ca3af';
    }
    const map: Record<string, string> = { A: '#ef4444', B: '#f97316', C: '#eab308', D: '#3b82f6', E: '#9ca3af' };
    return task.priority ? (map[task.priority] || '#6b7280') : '#6b7280';
}

function csvCell(value: string): string {
    return `"${(value ?? '').replace(/"/g, '""').replace(/\n/g, ' ')}"`;
}

const DEFAULT_GOAL = 'your goal of this week';

// ── Fetch shared export data (also used by PDF route) ──────────────────────

export async function fetchExportData(userId: string, startDate: string | null, endDate: string | null) {
    const where: any = { userId, completed: true, deletedAt: null };
    if (startDate || endDate) {
        where.updatedAt = {};
        if (startDate) where.updatedAt.gte = new Date(startDate);
        if (endDate) {
            const end = new Date(endDate);
            end.setHours(23, 59, 59, 999);
            where.updatedAt.lte = end;
        }
    }

    const [tasks, goals] = await Promise.all([
        prisma.task.findMany({
            where,
            orderBy: { updatedAt: 'desc' },
            include: {
                project:     { select: { name: true, color: true } },
                somedayList: { select: { title: true } },
            },
        }),
        prisma.weeklyGoal.findMany({
            where: { userId },
            select: { weekStart: true, text: true },
        }),
    ]);

    // Build week → goal map (weekStart is always Monday)
    const goalByWeek = new Map<string, string>();
    for (const g of goals) {
        if (g.text && g.text !== DEFAULT_GOAL) {
            goalByWeek.set(isoWeek(g.weekStart), g.text);
        }
    }

    // Group tasks by ISO week
    const byWeek = new Map<string, typeof tasks>();
    for (const task of tasks) {
        const key = isoWeek(task.updatedAt);
        if (!byWeek.has(key)) byWeek.set(key, []);
        byWeek.get(key)!.push(task);
    }

    return { byWeek, goalByWeek };
}

// ── CSV route ──────────────────────────────────────────────────────────────

export async function GET(request: Request) {
    const session = await getServerSession(authOptions);
    const { searchParams } = new URL(request.url);
    const startDate  = searchParams.get('startDate');
    const endDate    = searchParams.get('endDate');
    const lang       = searchParams.get('lang') || 'de';
    const de         = lang === 'de';

    const fieldsParam = searchParams.get('fields');
    const selectedFields: Set<ExportFieldKey> = fieldsParam
        ? new Set(fieldsParam.split(',') as ExportFieldKey[])
        : new Set(EXPORT_FIELDS.filter(f => f.defaultOn).map(f => f.key));

    if (!session?.user?.email) {
        return new NextResponse('Unauthorized', { status: 401 });
    }

    try {
        const user = await prisma.user.findUnique({ where: { email: session.user.email } });
        if (!user) return new NextResponse('User not found', { status: 404 });

        const { byWeek, goalByWeek } = await fetchExportData(user.id, startDate, endDate);

        // Build header — Title always first, then selected non-section fields
        const colFields = EXPORT_FIELDS.filter(f => selectedFields.has(f.key) && !f.csvOnly);
        const headerRow = [de ? 'Aufgabe' : 'Task', ...colFields.map(f => de ? f.labelDe : f.labelEn)];
        const rows: string[][] = [headerRow];

        for (const [weekKey, weekTasks] of byWeek) {
            // Week section header
            if (selectedFields.has('week')) {
                rows.push([weekLabel(weekKey, de), ...Array(headerRow.length - 1).fill('')]);
            }
            // Goal row
            const goal = goalByWeek.get(weekKey);
            if (selectedFields.has('weekGoal') && goal) {
                const goalLabel = de ? `Wochenziel: ${goal}` : `Goal: ${goal}`;
                rows.push([goalLabel, ...Array(headerRow.length - 1).fill('')]);
            }

            for (const t of weekTasks) {
                const row: string[] = [t.title || ''];
                for (const f of colFields) {
                    switch (f.key) {
                        case 'completedDate':  row.push(fmtDate(t.updatedAt, de)); break;
                        case 'scheduledDate':  row.push(fmtDate(t.scheduledDate ?? undefined, de)); break;
                        case 'createdDate':    row.push(fmtDate(t.createdAt, de)); break;
                        case 'project':        row.push(t.project?.name || ''); break;
                        case 'list':           row.push(t.somedayList?.title || ''); break;
                        case 'priority':       row.push(priorityLabel(t, de)); break;
                        case 'url':            row.push(t.url || ''); break;
                        case 'notes':          row.push((t.markdownContent || '').slice(0, 1000)); break;
                        case 'description':    row.push((t.description || '').slice(0, 500)); break;
                        case 'delegatedTo':    row.push(t.delegatedTo || ''); break;
                        case 'delegationNote': row.push(t.delegationNote || ''); break;
                        case 'startTime':      row.push(t.startTime || ''); break;
                        case 'kanbanStage':    row.push(t.kanbanStage || ''); break;
                    }
                }
                rows.push(row);
            }

            rows.push(Array(headerRow.length).fill(''));
        }

        const csvContent = rows.map(row => row.map(csvCell).join(',')).join('\r\n');
        const bom = '\uFEFF';
        const period = startDate && endDate ? `_${startDate}_${endDate}` : startDate ? `_ab_${startDate}` : endDate ? `_bis_${endDate}` : '';
        const filename = de
            ? `arbeitsbericht${period}_${new Date().toISOString().split('T')[0]}.csv`
            : `work-report${period}_${new Date().toISOString().split('T')[0]}.csv`;

        return new NextResponse(bom + csvContent, {
            headers: {
                'Content-Type': 'text/csv; charset=utf-8',
                'Content-Disposition': `attachment; filename="${filename}"`,
            },
        });
    } catch (error) {
        console.error('Export error:', error);
        return new NextResponse('Internal Server Error', { status: 500 });
    }
}
