<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Request;
use App\Core\Validator;
use App\Industry\Catalog;
use App\Models\Account;
use App\Models\AuditLog;
use App\Models\CampaignRecipient;
use App\Models\Contact;
use App\Models\Lead;
use App\Models\Opportunity;
use App\Models\Task;
use App\Models\Territory;
use App\Models\User;
use App\Services\IndustryService;

final class AccountController extends BaseController
{
    public function index(Request $request): void
    {
        $this->requireModule('accounts');
        $page = $this->page();
        $status = (string) ($_GET['status'] ?? 'active');
        if (!in_array($status, ['active', 'inactive'], true)) {
            $status = 'active';
        }
        $scope = $this->ownerScope();
        $result = Account::paginate($this->q(), $page, 15, $scope, $status);
        $label = account_label();
        view('accounts/index', [
            'title' => $label,
            'label' => $label,
            'rows' => $result['rows'],
            'total' => $result['total'],
            'page' => $page,
            'pages' => max(1, (int) ceil($result['total'] / 15)),
            'q' => $this->q(),
            'status' => $status,
            'counts' => Account::boardCounts($scope),
            'notifications' => $this->notifications(),
        ]);
    }

    public function show(Request $request): void
    {
        $this->requireModule('accounts');
        $id = (int) $request->param('id');
        $account = Account::detail($id);
        if (!$account) {
            flash('error', 'Account not found.');
            redirect('accounts');
        }
        view('accounts/show', [
            'title' => $account['name'],
            'account' => $account,
            'attrs' => IndustryService::decodeAttrs($account['attrs'] ?? null),
            'industry' => Catalog::current(),
            'contacts' => Contact::forAccount($id),
            'opportunities' => can_see('opportunities') ? Opportunity::forAccount($id) : [],
            'tasks' => Task::forRelated('account', $id),
            'timeline' => \App\Models\Activity::timeline('account', $id),
            'campaign_mail' => can_see('campaigns') || can_see('accounts') ? CampaignRecipient::forAccount($id) : [],
            'fromLead' => Lead::convertedToAccount($id),
            'salespeople' => User::salespeople(Auth::instance()->tenantId()),
            'servicePeople' => User::servicePeople(Auth::instance()->tenantId()),
            'quotes' => can_see('quotes') ? \App\Models\Quote::forAccount($id) : [],
            'orders' => can_see('orders') ? \App\Models\Order::forAccount($id) : [],
            'contracts' => can_see('contracts') ? \App\Models\Contract::forAccount($id) : [],
            'invoices' => can_see('invoices') ? \App\Models\Invoice::forAccount($id) : [],
            'jobs' => can_see('service_jobs') ? \App\Models\ServiceJob::forAccount($id) : [],
            'equipment' => can_see('equipment') ? \App\Models\Equipment::forAccount($id) : [],
            'notifications' => $this->notifications(),
        ]);
    }

    public function store(Request $request): void
    {
        $this->requireModule('accounts');
        $this->verifyCsrf($request);
        $data = $request->all();
        $v = (new Validator())->required($data, ['name' => 'Account name'])->max($data, 'name', 180, 'Account name');
        if (($data['email'] ?? '') !== '') {
            $v->email($data, 'email', 'Email');
        }
        if ($v->fails()) {
            $this->fail($v);
        }
        $id = Account::create([
            'name' => $data['name'],
            'phone' => $data['phone'] ?? null,
            'email' => $data['email'] ?? null,
            'website' => $data['website'] ?? null,
            'industry' => $data['industry'] ?? null,
            'territory_id' => !empty($data['territory_id']) ? (int) $data['territory_id'] : null,
            'owner_id' => (int) ($data['owner_id'] ?: Auth::instance()->id()),
            'status' => 'active',
            'city' => $data['city'] ?? null,
            'state' => $data['state'] ?? null,
            'attrs' => json_encode(IndustryService::sanitizeAttrs($data['attrs'] ?? [], entity_fields('account')), JSON_UNESCAPED_UNICODE),
        ]);
        AuditLog::write('account.create', 'account', $id);
        json_out(['ok' => true, 'id' => $id, 'redirect' => url('accounts/' . $id)]);
    }

    public function update(Request $request): void
    {
        $this->requireModule('accounts');
        $this->verifyCsrf($request);
        $id = (int) $request->param('id');
        $account = Account::find($id);
        if (!$account) {
            json_out(['ok' => false, 'error' => 'Not found.'], 404);
        }
        $data = $request->all();
        $v = (new Validator())->required($data, ['name' => 'Account name']);
        if ($v->fails()) {
            $this->fail($v);
        }
        $patch = [
            'name' => $data['name'],
            'phone' => $data['phone'] ?? null,
            'email' => $data['email'] ?? null,
            'website' => $data['website'] ?? null,
            'industry' => $data['industry'] ?? null,
            'owner_id' => (int) ($data['owner_id'] ?: $account['owner_id']),
            'status' => in_array($data['status'] ?? 'active', ['active', 'inactive'], true) ? $data['status'] : 'active',
            'next_action' => $data['next_action'] ?? null,
            'next_action_at' => $data['next_action_at'] ?: null,
            'city' => $data['city'] ?? null,
            'state' => $data['state'] ?? null,
            'attrs' => json_encode(IndustryService::sanitizeAttrs($data['attrs'] ?? [], entity_fields('account')), JSON_UNESCAPED_UNICODE),
        ];
        if (Catalog::isServiceSetup() && (can_see('service_visits') || has_role('salesperson', 'manager', 'admin'))) {
            $patch['service_assignee_id'] = !empty($data['service_assignee_id']) ? (int) $data['service_assignee_id'] : null;
        }
        Account::update($id, $patch);
        AuditLog::write('account.update', 'account', $id);
        json_out(['ok' => true]);
    }

    public function formData(Request $request): void
    {
        $this->requireModule('accounts');
        json_out([
            'ok' => true,
            'territories' => Territory::allForTenant(),
            'owners' => User::salespeople(Auth::instance()->tenantId()),
        ]);
    }
}
