<?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\AttachmentModel;
use App\Models\CommentModel;
use App\Models\CompanyModel;
use App\Models\NoteModel;
use App\Models\TagModel;
use App\Services\ActivityLogger;
use App\Services\ExportService;

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

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

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

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

        return $this->view('companies/index', [
            'title' => 'Companies',
            'activeNav' => 'companies',
            'breadcrumbs' => [['Home', 'dashboard'], ['CRM', 'companies'], ['Companies', 'companies']],
            'rows' => $rows,
            'meta' => $paginator->meta(),
            'lookups' => $this->lookups(),
        ]);
    }

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

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

        if ($request->isAjax() || $request->isJson()) {
            return AjaxResponse::success($company);
        }

        $pdo = Database::connection();
        $leads = $pdo->prepare("SELECT id, first_name, last_name, email FROM leads WHERE company_id = :id AND deleted_at IS NULL");
        $leads->execute(['id' => $id]);
        $customers = $pdo->prepare("SELECT id, first_name, last_name, email FROM customers WHERE company_id = :id AND deleted_at IS NULL");
        $customers->execute(['id' => $id]);

        return $this->view('companies/show', [
            'title' => $company['name'],
            'activeNav' => 'companies',
            'breadcrumbs' => [['Home', 'dashboard'], ['Companies', 'companies'], ['Company Details', 'companies/' . $id]],
            'company' => $company,
            'entityType' => 'company',
            'entityId' => $id,
            'relatedLeads' => $leads->fetchAll(),
            'relatedCustomers' => $customers->fetchAll(),
            'timeline' => ActivityLogger::timelineFor('company', $id),
            'notes' => (new NoteModel())->forEntity('company', $id),
            'comments' => (new CommentModel())->forEntity('company', $id),
            'attachments' => (new AttachmentModel())->forEntity('company', $id),
            'tags' => (new TagModel())->forEntity('company', $id),
            'lookups' => $this->lookups(),
        ]);
    }

    public function store(Request $request): Response
    {
        $data = $this->validateOrFail($request, [
            'name' => 'required|string|max:191',
            'business_line_id' => 'required|integer|exists:business_lines,id',
            'industry' => 'nullable|string|max:120',
            'website' => 'nullable|url|max:191',
            'phone' => 'nullable|string|max:30',
            'address_line1' => 'nullable|string|max:191',
            'city' => 'nullable|string|max:120',
            'province' => 'nullable|string|max:120',
            'postal_code' => 'nullable|string|max:20',
            'contract_status' => 'nullable|in:prospect,active,lapsed',
            'site_count' => 'nullable|integer',
            'annual_value' => 'nullable|numeric',
            'owner_id' => 'nullable|integer|exists:users,id',
        ]);

        $data['currency'] = 'CAD';
        $data['contract_status'] = $data['contract_status'] ?? 'prospect';

        $model = new CompanyModel();
        $id = $model->insert($data, $this->currentUserId());

        ActivityLogger::record('company', $id, 'company_created', "Company \"{$data['name']}\" created");

        return AjaxResponse::created($model->findWithRelations($id), 'Company created.');
    }

    public function update(Request $request, array $params): Response
    {
        $data = $this->validateOrFail($request, [
            'name' => 'required|string|max:191',
            'industry' => 'nullable|string|max:120',
            'website' => 'nullable|url|max:191',
            'phone' => 'nullable|string|max:30',
            'address_line1' => 'nullable|string|max:191',
            'city' => 'nullable|string|max:120',
            'province' => 'nullable|string|max:120',
            'postal_code' => 'nullable|string|max:20',
            'contract_status' => 'required|in:prospect,active,lapsed',
            'site_count' => 'nullable|integer',
            'annual_value' => 'nullable|numeric',
            'owner_id' => 'nullable|integer|exists:users,id',
        ]);

        $id = (int) $params['id'];
        $model = new CompanyModel();
        $model->update($id, $data, $this->currentUserId());

        ActivityLogger::record('company', $id, 'company_updated', 'Company details updated');

        return AjaxResponse::success($model->findWithRelations($id), 'Company updated.');
    }

    public function destroy(Request $request, array $params): Response
    {
        $id = (int) $params['id'];
        (new CompanyModel())->delete($id, $this->currentUserId());
        ActivityLogger::record('company', $id, 'company_deleted', 'Company moved to trash');

        return AjaxResponse::success(null, 'Company moved to trash.');
    }

    public function restore(Request $request, array $params): Response
    {
        $id = (int) $params['id'];
        (new CompanyModel())->restore($id);
        ActivityLogger::record('company', $id, 'company_restored', 'Company restored from trash', category: 'admin');

        return AjaxResponse::success(null, 'Company restored.');
    }

    public function export(Request $request): Response
    {
        $csv = (new ExportService())->exportCompanies([
            'search' => $request->query('search'),
            'business_line_id' => $request->query('business_line_id'),
        ]);

        return Response::html($csv)
            ->withHeader('Content-Type', 'text/csv; charset=UTF-8')
            ->withHeader('Content-Disposition', 'attachment; filename="companies-' . date('Y-m-d') . '.csv"');
    }

    private function lookups(): array
    {
        $pdo = Database::connection();

        return [
            'business_lines' => $pdo->query('SELECT id, name FROM business_lines ORDER BY name')->fetchAll(),
            'owners' => $pdo->query("SELECT id, CONCAT(first_name, ' ', last_name) AS name FROM users WHERE deleted_at IS NULL AND status = 'active' ORDER BY first_name")->fetchAll(),
        ];
    }
}
