<?php

declare(strict_types=1);

namespace App\Controllers;

use App\Core\BaseController;
use App\Core\Database;
use App\Core\Request;
use App\Core\Response;
use App\Helpers\AjaxResponse;
use App\Helpers\Paginator;
use App\Models\AudienceSegmentModel;
use App\Models\CampaignModel;
use App\Models\EmailTemplateModel;
use App\Services\ActivityLogger;
use App\Services\CampaignService;

final class CampaignController extends BaseController
{
    public function index(Request $request): Response
    {
        $model = new CampaignModel();
        $paginator = Paginator::fromRequest($request, defaultPerPage: 20);

        $filters = [
            'search' => $request->query('search'),
            'status' => $request->query('status'),
            'business_line_id' => $request->query('business_line_id'),
        ];

        $rows = $model->paginatedList($filters, $paginator);

        if ($request->isAjax() || $request->isJson()) {
            return AjaxResponse::success(['rows' => $rows, 'meta' => $paginator->meta()]);
        }

        return $this->view('marketing/campaigns', [
            'title' => 'Campaigns',
            'activeNav' => 'campaigns',
            'breadcrumbs' => [['Home', 'dashboard'], ['Marketing', 'campaigns'], ['Campaigns', 'campaigns']],
            'rows' => $rows,
            'meta' => $paginator->meta(),
            'lookups' => $this->lookups(),
        ]);
    }

    public function show(Request $request, array $params): Response
    {
        $id = (int) $params['id'];
        $model = new CampaignModel();
        $campaign = $model->findWithRelations($id);

        if ($campaign === null) {
            return Response::html('404 Not Found', 404);
        }

        $rates = (new \App\Services\TrackingService($model))->ratesFor($id);

        if ($request->isAjax() || $request->isJson()) {
            return AjaxResponse::success(['campaign' => $campaign, 'rates' => $rates]);
        }

        return $this->view('marketing/campaign-detail', [
            'title' => $campaign['name'],
            'activeNav' => 'campaigns',
            'breadcrumbs' => [['Home', 'dashboard'], ['Campaigns', 'campaigns'], [$campaign['name'], 'campaigns/' . $id]],
            'campaign' => $campaign,
            'rates' => $rates,
            'recipients' => $model->recipients($id),
        ]);
    }

    public function store(Request $request): Response
    {
        $data = $this->validateOrFail($request, [
            'name' => 'required|string|max:191',
            'subject' => 'required|string|max:255',
            'body_html' => 'required|string',
            'business_line_id' => 'nullable|integer|exists:business_lines,id',
            'email_template_id' => 'nullable|integer|exists:email_templates,id',
            'audience_segment_id' => 'nullable|integer|exists:audience_segments,id',
        ]);

        if (empty($data['audience_segment_id'])) {
            $filter = $request->input('audience_filter');
            if (!is_array($filter) || $filter === []) {
                return AjaxResponse::validationError(['audience_filter' => ['Choose a saved segment or define who this campaign is going to.']]);
            }
            $data['audience_filter'] = json_encode($filter);
        }

        $recurrence = $request->input('recurrence_rule');
        if (is_array($recurrence) && !empty($recurrence['frequency'])) {
            $data['recurrence_rule'] = $recurrence;
        }

        $id = (new CampaignService())->createDraft($data, $this->currentUserId());
        ActivityLogger::record('campaign', $id, 'campaign_created', "Created campaign \"{$data['name']}\"");

        return AjaxResponse::created(['id' => $id], 'Campaign saved as draft.');
    }

    public function sendNow(Request $request, array $params): Response
    {
        $result = (new CampaignService())->sendNow((int) $params['id'], $this->currentUserId());

        return $result['success'] ? AjaxResponse::success($result, $result['message']) : AjaxResponse::error($result['message'], 422);
    }

    public function schedule(Request $request, array $params): Response
    {
        $data = $this->validateOrFail($request, ['send_at' => 'required|date']);
        $result = (new CampaignService())->schedule((int) $params['id'], $data['send_at'], $this->currentUserId());

        return $result['success'] ? AjaxResponse::success($result, $result['message']) : AjaxResponse::error($result['message'], 422);
    }

    public function cancel(Request $request, array $params): Response
    {
        (new CampaignService())->cancel((int) $params['id'], $this->currentUserId());

        return AjaxResponse::success(null, 'Campaign cancelled.');
    }

    public function destroy(Request $request, array $params): Response
    {
        $id = (int) $params['id'];
        (new CampaignModel())->delete($id, $this->currentUserId());
        ActivityLogger::record('campaign', $id, 'campaign_deleted', 'Campaign deleted');

        return AjaxResponse::success(null, 'Campaign deleted.');
    }

    /** Live "N recipients" preview for the builder — same resolution logic actually used at send time. */
    public function previewAudience(Request $request): Response
    {
        $definition = $request->input('filter', []);
        $count = (new \App\Services\AudienceSegmentService())->previewCount(is_array($definition) ? $definition : []);

        return AjaxResponse::success(['count' => $count]);
    }

    private function lookups(): array
    {
        return [
            'business_lines' => Database::connection()->query('SELECT id, name FROM business_lines ORDER BY name')->fetchAll(),
            'templates' => (new EmailTemplateModel())->allWithBusinessLine(),
            'segments' => (new AudienceSegmentModel())->allActive(),
        ];
    }
}
