<?php

namespace App\Exports;

use App\DTO\ReportFilters;
use App\Models\Project;
use Maatwebsite\Excel\Concerns\FromArray;
use Maatwebsite\Excel\Concerns\WithColumnWidths;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMultipleSheets;
use Maatwebsite\Excel\Concerns\WithStyles;
use Maatwebsite\Excel\Concerns\WithTitle;
use PhpOffice\PhpSpreadsheet\Style\Alignment;
use PhpOffice\PhpSpreadsheet\Style\Border;
use PhpOffice\PhpSpreadsheet\Style\Fill;
use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet;

class ProjectReportExport implements WithMultipleSheets
{
    protected Project $project;

    protected ReportFilters $filters;

    protected array $data;

    public function __construct(Project $project, ReportFilters $filters, array $data)
    {
        $this->project = $project;
        $this->filters = $filters;
        $this->data = $data;
    }

    public function sheets(): array
    {
        $sheets = [
            new SummarySheet($this->data['summary'] ?? [], $this->project, $this->filters),
        ];

        if (! empty($this->data['phases'])) {
            $sheets[] = new PhasesSheet($this->data['phases']);
        }

        if (! empty($this->data['features'])) {
            $sheets[] = new FeaturesSheet($this->data['features']);
        }

        if (! empty($this->data['inspections'])) {
            $sheets[] = new InspectionsSheet($this->data['inspections']);
        }

        if (! empty($this->data['issues'])) {
            $sheets[] = new IssuesSheet($this->data['issues']);
        }

        if (! empty($this->data['tasks'])) {
            $sheets[] = new TasksSheet($this->data['tasks']);
        }

        if (! empty($this->data['deviations'])) {
            $sheets[] = new DeviationsSheet($this->data['deviations']);
        }

        if (! empty($this->data['media'])) {
            $sheets[] = new MediaSheet($this->data['media']);
        }

        if (! empty($this->data['progress_curve'])) {
            $sheets[] = new ProgressCurveSheet($this->data['progress_curve']);
        }

        // Parameters sheet
        $sheets[] = new ParametersSheet($this->filters, $this->project);

        return $sheets;
    }
}

// ============================================================
// Base Sheet with common styling
// ============================================================

abstract class BaseSheet implements FromArray, WithColumnWidths, WithHeadings, WithStyles, WithTitle
{
    protected array $rows = [];

    public function __construct(array $data = [])
    {
        $this->rows = $data;
    }

    public function array(): array
    {
        return $this->rows;
    }

    abstract public function headings(): array;

    public function title(): string
    {
        return static::class;
    }

    public function styles(Worksheet $sheet)
    {
        // Header row style
        $sheet->getStyle('1:1')->applyFromArray([
            'font' => ['bold' => true, 'color' => ['rgb' => 'FFFFFF'], 'size' => 11],
            'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => '1E3A8A']],
            'alignment' => ['horizontal' => Alignment::HORIZONTAL_CENTER, 'wrapText' => true],
            'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]],
        ]);

        // Data rows
        $highestRow = $sheet->getHighestRow();
        if ($highestRow > 1) {
            $sheet->getStyle("2:{$highestRow}")->applyFromArray([
                'font' => ['size' => 10],
                'alignment' => ['vertical' => Alignment::VERTICAL_CENTER, 'wrapText' => true],
                'borders' => ['allBorders' => ['borderStyle' => Border::BORDER_THIN]],
            ]);

            // Alternate row colors
            for ($row = 2; $row <= $highestRow; $row++) {
                if ($row % 2 === 0) {
                    $sheet->getStyle("{$row}:{$row}")->applyFromArray([
                        'fill' => ['fillType' => Fill::FILL_SOLID, 'startColor' => ['rgb' => 'F8FAFC']],
                    ]);
                }
            }
        }

        // Auto-filter
        $sheet->setAutoFilter($sheet->calculateWorksheetDimension());

        // Freeze header row
        $sheet->freezePane('A2');
    }

    public function columnWidths(): array
    {
        return [];
    }
}

// ============================================================
// Summary Sheet
// ============================================================

class SummarySheet extends BaseSheet
{
    protected Project $project;

    protected ReportFilters $filters;

    public function __construct(array $summary, Project $project, ReportFilters $filters)
    {
        $this->project = $project;
        $this->filters = $filters;

        $rows = [
            ['Informe de Proyecto', $project->name],
            ['Referencia', $project->reference ?? '—'],
            ['Dirección', $project->address ?? '—'],
            ['Estado', $project->status ?? '—'],
            ['Fecha inicio', $project->start_date?->format('d/m/Y') ?? '—'],
            ['Fecha fin estimada', $project->end_date_estimated?->format('d/m/Y') ?? '—'],
            ['', ''],
            ['Período del informe', $filters->getDateRangeLabel()],
            ['Generado el', now()->format('d/m/Y H:i')],
            ['Generado por', auth()->guard()->user()?->name ?? 'Sistema'],
            ['', ''],
            ['--- RESUMEN EJECUTIVO ---', ''],
            ['Total elementos', $summary['total_features'] ?? 0],
            ['Elementos completados', $summary['completed_features'] ?? 0],
            ['Tasa completitud (%)', $summary['completion_rate'] ?? 0],
            ['Progreso planificado medio (%)', $summary['avg_planned_progress'] ?? 0],
            ['Progreso real medio (%)', $summary['avg_actual_progress'] ?? 0],
            ['SPI global', $summary['overall_spi'] ?? 'N/A'],
            ['', ''],
            ['--- INSPECCIONES ---', ''],
            ['Total inspecciones', $summary['total_inspections'] ?? 0],
            ['Aprobadas', $summary['passed_inspections'] ?? 0],
            ['Fallidas', $summary['failed_inspections'] ?? 0],
            ['Tasa aprobación (%)', $summary['pass_rate'] ?? 0],
            ['', ''],
            ['--- INCIDENCIAS ---', ''],
            ['Abiertas', $summary['open_issues'] ?? 0],
            ['Cerradas', $summary['closed_issues'] ?? 0],
            ['', ''],
            ['--- TAREAS ---', ''],
            ['Total tareas', $summary['total_tasks'] ?? 0],
            ['Completadas', $summary['completed_tasks'] ?? 0],
            ['Tasa completitud (%)', $summary['task_completion_rate'] ?? 0],
            ['', ''],
            ['--- FASES ---', ''],
            ['En plazo', $summary['phases_on_track'] ?? 0],
            ['Retrasadas', $summary['phases_delayed'] ?? 0],
            ['Sin datos', $summary['phases_no_data'] ?? 0],
        ];

        parent::__construct($rows);
    }

    public function headings(): array
    {
        return ['Concepto', 'Valor'];
    }

    public function columnWidths(): array
    {
        return ['A' => 40, 'B' => 30];
    }
}

// ============================================================
// Phases Sheet
// ============================================================

class PhasesSheet extends BaseSheet
{
    public function headings(): array
    {
        return [
            'ID', 'Fase', 'Orden', 'Color', 'Inicio Plan', 'Fin Plan',
            'Inicio Real', 'Fin Real', 'Progreso (%)', 'Progreso Plan (%)',
            'Desvío Fin (días)', 'Desvío Inicio (días)', 'SPI', 'En Plazo',
            'Elementos', 'Completados', 'Capas',
        ];
    }

    public function array(): array
    {
        return array_map(function ($phase) {
            return [
                $phase['id'],
                $phase['name'],
                $phase['order'],
                $phase['color'],
                $phase['planned_start'] ?? '—',
                $phase['planned_end'] ?? '—',
                $phase['actual_start'] ?? '—',
                $phase['actual_end'] ?? '—',
                $phase['progress_percent'],
                $phase['planned_progress'],
                $phase['deviation_days'] ?? '—',
                $phase['start_deviation_days'] ?? '—',
                $phase['spi'] ?? '—',
                $phase['is_on_track'] === true ? 'Sí' : ($phase['is_on_track'] === false ? 'No' : 'N/A'),
                $phase['features_count'],
                $phase['completed_features'],
                count($phase['layers']),
            ];
        }, $this->rows);
    }

    public function columnWidths(): array
    {
        return ['A' => 8, 'B' => 25, 'C' => 8, 'D' => 10, 'E' => 12, 'F' => 12,
            'G' => 12, 'H' => 12, 'I' => 12, 'J' => 14, 'K' => 14, 'L' => 14,
            'M' => 8, 'N' => 10, 'O' => 10, 'P' => 12, 'Q' => 10];
    }
}

// ============================================================
// Features Sheet
// ============================================================

class FeaturesSheet extends BaseSheet
{
    public function headings(): array
    {
        return [
            'ID', 'Elemento', 'Fase', 'Capa', 'Estado', 'Progreso (%)', 'Progreso Plan (%)',
            'Inicio Plan', 'Fin Plan', 'Inicio Real', 'Fin Real', 'Desvío Fin (días)',
            'Desvío Inicio (días)', 'SPI', 'En Plazo', 'Responsable', 'Template',
            'Última Inspección', 'Resultado', 'Inspecciones', 'Issues Abiertos',
        ];
    }

    public function array(): array
    {
        return array_map(function ($feature) {
            return [
                $feature['id'],
                $feature['name'],
                $feature['phase'],
                $feature['layer'],
                $feature['status_label'],
                $feature['progress'],
                $feature['planned_progress'],
                $feature['planned_start'] ?? '—',
                $feature['planned_end'] ?? '—',
                $feature['actual_start'] ?? '—',
                $feature['actual_end'] ?? '—',
                $feature['deviation_days'] ?? '—',
                $feature['start_deviation_days'] ?? '—',
                $feature['spi'] ?? '—',
                $feature['is_on_track'] === true ? 'Sí' : ($feature['is_on_track'] === false ? 'No' : 'N/A'),
                $feature['responsible'],
                $feature['template'],
                $feature['last_inspection_date'] ?? '—',
                $feature['last_inspection_result'] ?? '—',
                $feature['inspections_count'],
                $feature['open_issues_count'],
            ];
        }, $this->rows);
    }

    public function columnWidths(): array
    {
        return ['A' => 8, 'B' => 25, 'C' => 20, 'D' => 20, 'E' => 15, 'F' => 12,
            'G' => 14, 'H' => 12, 'I' => 12, 'J' => 12, 'K' => 12, 'L' => 14,
            'M' => 14, 'N' => 8, 'O' => 10, 'P' => 20, 'Q' => 20, 'R' => 14,
            'S' => 12, 'T' => 12, 'U' => 12];
    }
}

// ============================================================
// Inspections Sheet
// ============================================================

class InspectionsSheet extends BaseSheet
{
    public function headings(): array
    {
        return [
            'ID', 'Elemento', 'Fase', 'Template', 'Inspector', 'Fecha',
            'Estado', 'Resultado', 'Notas', 'Fotos',
        ];
    }

    public function array(): array
    {
        return array_map(function ($inspection) {
            return [
                $inspection['id'],
                $inspection['feature'],
                $inspection['phase'],
                $inspection['template'],
                $inspection['inspector'],
                $inspection['date'],
                $inspection['status'],
                $inspection['result_label'],
                $inspection['notes'] ?? '—',
                $inspection['photos_count'],
            ];
        }, $this->rows);
    }

    public function columnWidths(): array
    {
        return ['A' => 8, 'B' => 25, 'C' => 20, 'D' => 25, 'E' => 20, 'F' => 18,
            'G' => 12, 'H' => 12, 'I' => 40, 'J' => 8];
    }
}

// ============================================================
// Issues Sheet
// ============================================================

class IssuesSheet extends BaseSheet
{
    public function headings(): array
    {
        return [
            'ID', 'Título', 'Elemento', 'Fase', 'Prioridad', 'Estado',
            'Reportado por', 'Asignado a', 'Creado', 'Cerrado', 'Días abierto',
            'Tareas total', 'Tareas completadas',
        ];
    }

    public function array(): array
    {
        return array_map(function ($issue) {
            return [
                $issue['id'],
                $issue['title'],
                $issue['feature'],
                $issue['phase'],
                $issue['priority_label'],
                $issue['status_label'],
                $issue['reporter'],
                $issue['assignee'],
                $issue['created_at'],
                $issue['closed_at'] ?? '—',
                $issue['days_open'],
                $issue['tasks_total'],
                $issue['tasks_completed'],
            ];
        }, $this->rows);
    }

    public function columnWidths(): array
    {
        return ['A' => 8, 'B' => 35, 'C' => 20, 'D' => 20, 'E' => 12, 'F' => 15,
            'G' => 20, 'H' => 20, 'I' => 12, 'J' => 12, 'K' => 12, 'L' => 12, 'M' => 14];
    }
}

// ============================================================
// Tasks Sheet
// ============================================================

class TasksSheet extends BaseSheet
{
    public function headings(): array
    {
        return [
            'ID', 'Tarea', 'Fase', 'Estado', 'Prioridad', 'Asignado', 'Creador',
            'Fecha inicio', 'Fecha fin', 'Completada', 'Horas est.', 'Horas real',
            'Progreso (%)', 'Vencida', 'Subtareas',
        ];
    }

    public function array(): array
    {
        return array_map(function ($task) {
            $subtasksStr = implode('; ', array_map(fn ($st) => "{$st['title']} ({$st['status']})", $task['subtasks']));

            return [
                $task['id'],
                $task['title'],
                $task['phase'],
                $task['status_label'],
                $task['priority_label'],
                $task['assignee'],
                $task['creator'],
                $task['start_date'] ?? '—',
                $task['due_date'] ?? '—',
                $task['completed_at'] ?? '—',
                $task['estimated_hours'] ?? '—',
                $task['actual_hours'] ?? '—',
                $task['progress'],
                $task['is_overdue'] ? 'Sí' : 'No',
                $subtasksStr ?: '—',
            ];
        }, $this->rows);
    }

    public function columnWidths(): array
    {
        return ['A' => 8, 'B' => 30, 'C' => 20, 'D' => 15, 'E' => 12, 'F' => 20,
            'G' => 20, 'H' => 12, 'I' => 12, 'J' => 12, 'K' => 10, 'L' => 10,
            'M' => 12, 'N' => 10, 'O' => 40];
    }
}

// ============================================================
// Deviations Sheet
// ============================================================

class DeviationsSheet extends BaseSheet
{
    protected array $deviations;

    public function __construct(array $deviations)
    {
        $this->deviations = $deviations;
        $rows = [];

        // Phase deviations
        if (! empty($deviations['phases'])) {
            $rows[] = ['=== DESVÍOS POR FASE ===', '', '', '', '', '', '', '', '', '', ''];
            $rows[] = ['ID', 'Fase', 'Inicio Plan', 'Fin Plan', 'Inicio Real', 'Fin Real',
                'Desvío Inicio (d)', 'Desvío Fin (d)', 'Prog. Plan (%)', 'Prog. Real (%)',
                'Desvío Prog.', 'SPI', 'En Plazo'];

            foreach ($deviations['phases'] as $phase) {
                $rows[] = [
                    $phase['id'], $phase['name'], $phase['planned_start'], $phase['planned_end'],
                    $phase['actual_start'], $phase['actual_end'],
                    $phase['start_deviation'] ?? '—', $phase['end_deviation'] ?? '—',
                    $phase['planned_progress'], $phase['actual_progress'],
                    $phase['progress_deviation'], $phase['spi'] ?? '—',
                    $phase['is_on_track'] === true ? 'Sí' : ($phase['is_on_track'] === false ? 'No' : 'N/A'),
                ];
            }
            $rows[] = ['', '', '', '', '', '', '', '', '', '', ''];
        }

        // Feature deviations
        if (! empty($deviations['features'])) {
            $rows[] = ['=== DESVÍOS POR ELEMENTO ===', '', '', '', '', '', '', '', '', '', '', '', ''];
            $rows[] = ['ID', 'Elemento', 'Fase', 'Inicio Plan', 'Fin Plan', 'Inicio Real', 'Fin Real',
                'Desvío Inicio (d)', 'Desvío Fin (d)', 'Prog. Plan (%)', 'Prog. Real (%)',
                'Desvío Prog.', 'SPI', 'En Plazo', 'Responsable'];

            foreach ($deviations['features'] as $feature) {
                $rows[] = [
                    $feature['id'], $feature['name'], $feature['phase'],
                    $feature['planned_start'], $feature['planned_end'],
                    $feature['actual_start'], $feature['actual_end'],
                    $feature['start_deviation'] ?? '—', $feature['end_deviation'] ?? '—',
                    $feature['planned_progress'], $feature['actual_progress'],
                    $feature['progress_deviation'], $feature['spi'] ?? '—',
                    $feature['is_on_track'] === true ? 'Sí' : ($feature['is_on_track'] === false ? 'No' : 'N/A'),
                    $feature['responsible'],
                ];
            }
            $rows[] = ['', '', '', '', '', '', '', '', '', '', '', '', '', ''];
        }

        // Summary
        if (! empty($deviations['summary'])) {
            $rows[] = ['=== RESUMEN DESVÍOS ===', ''];
            $rows[] = ['Fases retrasadas', $deviations['summary']['phases_delayed'] ?? 0];
            $rows[] = ['Fases adelantadas', $deviations['summary']['phases_early'] ?? 0];
            $rows[] = ['Fases en plazo', $deviations['summary']['phases_on_time'] ?? 0];
            $rows[] = ['Elementos retrasados', $deviations['summary']['features_delayed'] ?? 0];
            $rows[] = ['Elementos adelantados', $deviations['summary']['features_early'] ?? 0];
            $rows[] = ['Elementos en plazo', $deviations['summary']['features_on_time'] ?? 0];
        }

        $this->rows = $rows;
    }

    public function headings(): array
    {
        return []; // Headings included in data rows
    }

    public function title(): string
    {
        return 'Desvíos';
    }

    public function columnWidths(): array
    {
        return ['A' => 25, 'B' => 25, 'C' => 20, 'D' => 12, 'E' => 12, 'F' => 12,
            'G' => 12, 'H' => 14, 'I' => 14, 'J' => 14, 'K' => 14, 'L' => 10,
            'M' => 10, 'N' => 20];
    }
}

// ============================================================
// Media Sheet
// ============================================================

class MediaSheet extends BaseSheet
{
    public function headings(): array
    {
        return ['ID', 'Nombre', 'Tipo', 'Entidad', 'Entidad Nombre', 'Tamaño', 'Subido por', 'Fecha', 'URL'];
    }

    public function array(): array
    {
        return array_map(function ($media) {
            return [
                $media['id'],
                $media['name'],
                $media['type'],
                $media['entity'],
                $media['entity_name'],
                $media['size'],
                $media['uploaded_by'],
                $media['uploaded_at'],
                $media['url'],
            ];
        }, $this->rows);
    }

    public function columnWidths(): array
    {
        return ['A' => 8, 'B' => 30, 'C' => 12, 'D' => 15, 'E' => 30, 'F' => 12,
            'G' => 20, 'H' => 18, 'I' => 50];
    }
}

// ============================================================
// Progress Curve Sheet
// ============================================================

class ProgressCurveSheet extends BaseSheet
{
    protected array $curveData;

    public function __construct(array $curveData)
    {
        $this->curveData = $curveData;

        $rows = [['Fecha', 'Progreso Planificado (%)', 'Progreso Real (%)']];

        $labels = $curveData['labels'] ?? [];
        $planned = $curveData['planned'] ?? [];
        $actual = $curveData['actual'] ?? [];

        for ($i = 0; $i < count($labels); $i++) {
            $rows[] = [$labels[$i], $planned[$i] ?? 0, $actual[$i] ?? 0];
        }

        $this->rows = $rows;
    }

    public function headings(): array
    {
        return ['Fecha', 'Progreso Planificado (%)', 'Progreso Real (%)'];
    }

    public function title(): string
    {
        return 'Curva S';
    }

    public function columnWidths(): array
    {
        return ['A' => 14, 'B' => 22, 'C' => 20];
    }
}

// ============================================================
// Parameters Sheet
// ============================================================

class ParametersSheet extends BaseSheet
{
    protected ReportFilters $filters;

    protected Project $project;

    public function __construct(ReportFilters $filters, Project $project)
    {
        $this->filters = $filters;
        $this->project = $project;

        $rows = [
            ['Parámetro', 'Valor'],
            ['Proyecto', $project->name],
            ['Referencia', $project->reference ?? '—'],
            ['Fecha desde', $filters->dateFrom?->format('d/m/Y') ?? '—'],
            ['Fecha hasta', $filters->dateTo?->format('d/m/Y') ?? '—'],
            ['Entidades incluidas', implode(', ', array_map(
                fn ($e) => $filters->getAvailableEntities()[$e] ?? $e,
                $filters->entityTypes
            ))],
            ['Incluir fotos', $filters->includePhotos ? 'Sí' : 'No'],
            ['Formato', strtoupper($filters->format)],
            ['Incluir gráficos', $filters->includeCharts ? 'Sí' : 'No'],
            ['Generado', now()->format('d/m/Y H:i')],
            ['Generado por', auth()->guard()->user()?->name ?? 'Sistema'],
        ];

        parent::__construct($rows);
    }

    public function headings(): array
    {
        return ['Parámetro', 'Valor'];
    }

    public function title(): string
    {
        return 'Parámetros';
    }

    public function columnWidths(): array
    {
        return ['A' => 30, 'B' => 50];
    }
}
