<?php

namespace App\Controllers;

use App\Services\PacingReport\PacingReportService;

/**
 * Pacing Report — Hearst-only AdCenter page (AP-103).
 *
 * Clone of legacy advertisers7_new/adcenter/controllers/Campaigns.php::pace()
 * + getPaceJSON(). The CI3 cookie-persisted daterange is replaced with URL
 * params (DataTables sends `from`/`to`/`show_aggregate_report` as query args
 * on every AJAX call; no session/cookie needed).
 *
 * Gated by HearstFilter via Routes.php — non-Hearst advertisers 404.
 */
class PacingReport extends BaseController
{
    public function index()
    {
        $data = $this->data;
        $data['title']     = 'Pacing Report';
        $data['pageTitle'] = 'Pacing Report';
        $data['activeNav'] = 'pacing-report';

        return view('pacing-report/index', $data);
    }

    /**
     * AJAX endpoint backing the legacy DataTable. Returns the same JSON
     * envelope shape as legacy: {data: [...], total: N}.
     */
    public function getPaceJSON()
    {
        $advId = (int) auth_adv_id();
        if ($advId <= 0) {
            return $this->response
                ->setStatusCode(401)
                ->setJSON(['status' => false, 'message' => 'Session expired']);
        }

        [$from, $to, $showAggregate] = $this->resolveParams();

        $service = new PacingReportService();
        $payload = $service->build($advId, $from, $to, $showAggregate);

        return $this->response
            ->setContentType('application/json')
            ->setJSON($payload);
    }

    /**
     * CSV export of the same data the table shows. Mirrors getPaceJSON()'s
     * param resolution and advertiser resolution exactly, so the download
     * always matches what's currently on screen.
     */
    public function csvExport()
    {
        $advId = (int) auth_adv_id();
        if ($advId <= 0) {
            return $this->response
                ->setStatusCode(401)
                ->setJSON(['status' => false, 'message' => 'Session expired']);
        }

        [$from, $to, $showAggregate] = $this->resolveParams();

        $service = new PacingReportService();
        $payload = $service->build($advId, $from, $to, $showAggregate);

        $headers = [
            'Id', 'Name', 'Start Date', 'End Date', 'Type', 'Bid', 'Budget',
            'Impressions', 'Clicks', 'Spent', 'CTR', 'Avg CPC', 'Avg CPM', 'Conversions',
            'Total Impressions', 'Total Clicks', 'Total Budget',
            'Lifetime Impressions', 'Lifetime Clicks', 'Lifetime Spent',
        ];
        $fields = [
            'id', 'name', 'start_date', 'end_date', 'type_label', 'bid', 'budget',
            'impressions', 'clicks', 'spent', 'ctr', 'avgcpc', 'avgcpm', 'conversions',
            'total_impressions', 'total_clicks', 'total_budget',
            'lifetime_impressions', 'lifetime_clicks', 'lifetime_spent',
        ];

        $out = fopen('php://temp', 'r+');
        fputcsv($out, $headers);
        foreach ($payload['data'] as $row) {
            $line = [];
            foreach ($fields as $field) {
                $value = $row[$field] ?? '';
                // Avoid PHP's default float-to-string cast switching to
                // scientific notation (e.g. 0.00002 -> "2.0E-5") in the CSV.
                if (is_float($value)) {
                    $value = rtrim(rtrim(sprintf('%.10f', $value), '0'), '.');
                }
                $line[] = $value;
            }
            fputcsv($out, $line);
        }
        rewind($out);
        $csv = stream_get_contents($out);
        fclose($out);

        $filename = "pacing-report-{$from}-to-{$to}.csv";

        return $this->response
            ->setHeader('Content-Type', 'text/csv; charset=UTF-8')
            ->setHeader('Content-Disposition', "attachment; filename=\"{$filename}\"")
            ->setHeader('Cache-Control', 'no-store, no-cache')
            ->setBody($csv);
    }

    /**
     * Shared from/to/show_aggregate_report resolution for getPaceJSON() and
     * csvExport(). DataTables sends these as POST body params (see
     * pacing-report.js), but a direct CSV download link is a plain GET —
     * checking POST first, falling back to GET, covers both.
     *
     * @return array{0: string, 1: string, 2: bool}
     */
    private function resolveParams(): array
    {
        $from = $this->request->getPost('from') ?: $this->request->getGet('from');
        $to   = $this->request->getPost('to')   ?: $this->request->getGet('to');
        if (!$from || !preg_match('/^\d{4}-\d{2}-\d{2}$/', (string) $from)) {
            $from = date('Y-m-d');
        }
        if (!$to || !preg_match('/^\d{4}-\d{2}-\d{2}$/', (string) $to)) {
            $to = date('Y-m-d');
        }
        if ($from > $to) {
            [$from, $to] = [$to, $from];
        }

        $showAggregate = (bool) ($this->request->getPost('show_aggregate_report') ?: $this->request->getGet('show_aggregate_report'));

        return [$from, $to, $showAggregate];
    }
}
