<?php

namespace WPD\Report;

use WPD\Domain\ScanContext;

final class ReportBuilder
{
    const VERSION = '0.2.0';

    public function build(array $state, ScanContext $context)
    {
        $findings = isset($state['findings']) && is_array($state['findings']) ? $state['findings'] : array();
        usort($findings, array($this, 'compareFindings'));
        $counts = array('problema confirmado' => 0, 'causa probable' => 0, 'advertencia' => 0, 'información' => 0);
        foreach ($findings as $finding) {
            if (isset($counts[$finding['certainty']])) {
                $counts[$finding['certainty']]++;
            }
        }

        $partial = false;
        foreach (isset($state['checks']) ? $state['checks'] : array() as $check) {
            if (in_array($check['status'], array('parcial', 'no disponible', 'error de comprobación'), true)) {
                $partial = true;
                break;
            }
        }
        foreach ($findings as $finding) {
            if (isset($finding['coverage']) && $finding['coverage'] === 'parcial') {
                $partial = true;
                break;
            }
        }

        $incompleteChecks = array();
        foreach (isset($state['checks']) ? $state['checks'] : array() as $id => $check) {
            if (!isset($check['status']) || $check['status'] === 'correcta') {
                continue;
            }
            $incompleteChecks[$id] = array(
                'label' => isset($check['label']) ? $check['label'] : 'Comprobación',
                'status' => $check['status'],
            );
        }

        return $context->redactor()->data(array(
            'schema_version' => 1,
            'tool_version' => self::VERSION,
            'scan_id' => isset($state['scan_id']) ? $state['scan_id'] : '',
            'coverage' => $partial ? 'parcial' : 'completa',
            'counts' => $counts,
            'summary' => $this->summary($findings, $partial),
            'findings' => $findings,
            'checks' => $incompleteChecks,
        ));
    }

    public function json(array $report)
    {
        return json_encode($report, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
    }

    public function standaloneHtml(array $report)
    {
        $title = 'Informe de diagnóstico de WordPress';
        $html = '<!doctype html><html lang="es"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">';
        $html .= '<title>' . wpd_escape($title) . '</title><style>' . $this->exportCss() . '</style></head><body><main>';
        $html .= '<p class="eyebrow">Herramienta de diagnóstico para WordPress · v' . wpd_escape($report['tool_version']) . '</p>';
        $html .= '<h1>' . wpd_escape($title) . '</h1><p class="summary">' . wpd_escape($report['summary']) . '</p>';
        $html .= '<dl><div><dt>Confirmados</dt><dd>' . (int) $report['counts']['problema confirmado'] . '</dd></div><div><dt>Probables</dt><dd>' . (int) $report['counts']['causa probable'] . '</dd></div><div><dt>Cobertura</dt><dd>' . wpd_escape($report['coverage']) . '</dd></div></dl>';
        foreach ($report['findings'] as $finding) {
            $html .= '<article><p class="meta">' . wpd_escape($finding['certainty']) . ' · ' . wpd_escape($finding['severity']) . '</p>';
            $html .= '<h2>' . wpd_escape($finding['title']) . '</h2><p><strong>Prueba:</strong> ' . wpd_escape($finding['evidence']) . '</p><p>' . wpd_escape($finding['explanation']) . '</p>';
            $html .= '<h3>Solución recomendada</h3><ol>';
            foreach ($finding['solution'] as $step) {
                $html .= '<li>' . wpd_escape($step) . '</li>';
            }
            $html .= '</ol><p><strong>Después:</strong> ' . wpd_escape($finding['verification']) . '</p></article>';
        }
        $html .= '<p class="warning">Este informe es de solo lectura. Haz una copia de seguridad antes de aplicar cambios manuales.</p></main></body></html>';
        return $html;
    }

    private function summary(array $findings, $partial)
    {
        $primary = array();
        foreach ($findings as $finding) {
            if (in_array($finding['certainty'], array('problema confirmado', 'causa probable'), true)) {
                $primary[] = $finding['title'];
            }
            if (count($primary) === 2) {
                break;
            }
        }
        if (!$primary) {
            $text = 'No se ha confirmado una causa directa. Revisa las advertencias y las fases no disponibles antes de considerar correcta la instalación.';
        } else {
            $text = 'Las causas principales detectadas son: ' . implode('; ', $primary) . '.';
        }
        if ($partial) {
            $text .= ' La cobertura es parcial y no equivale a un resultado limpio.';
        }
        return $text;
    }

    private function compareFindings(array $a, array $b)
    {
        $certainty = array('problema confirmado' => 0, 'causa probable' => 1, 'advertencia' => 2, 'información' => 3);
        $severity = array('crítica' => 0, 'alta' => 1, 'media' => 2, 'baja' => 3, 'informativa' => 4);
        $aValue = (isset($certainty[$a['certainty']]) ? $certainty[$a['certainty']] : 9) * 10 + (isset($severity[$a['severity']]) ? $severity[$a['severity']] : 9);
        $bValue = (isset($certainty[$b['certainty']]) ? $certainty[$b['certainty']] : 9) * 10 + (isset($severity[$b['severity']]) ? $severity[$b['severity']] : 9);
        return $aValue === $bValue ? strcmp($a['title'], $b['title']) : ($aValue < $bValue ? -1 : 1);
    }

    private function exportCss()
    {
        return 'body{margin:0;background:#f6f5f1;color:#1d2522;font:16px/1.6 system-ui,sans-serif}main{max-width:850px;margin:auto;padding:48px 22px}.eyebrow,.meta{color:#53645d;text-transform:uppercase;letter-spacing:.08em;font-size:13px}.summary{font-size:21px}dl{display:flex;gap:28px;flex-wrap:wrap;margin:32px 0}dt{font-size:13px;color:#617069}dd{margin:0;font-weight:700}article{border-top:1px solid #cfd5d1;padding:30px 0}h1{font-size:40px;line-height:1.1}h2{font-size:26px;line-height:1.2}.warning{border-left:5px solid #be7a20;background:#fff7e8;padding:16px 18px}@media(max-width:600px){main{padding:30px 18px}h1{font-size:32px}}';
    }
}
