<?php
declare(strict_types=1);

namespace App\Controllers;

use App\Core\Auth;
use App\Core\Request;
use App\Core\Validator;
use App\Models\Account;
use App\Models\AuditLog;
use App\Models\PortalDocument;
use App\Models\Signature;
use App\Models\User;
use App\Services\DocumentStore;
use App\Services\RecordService;

final class DocumentController extends BaseController
{
    public function index(Request $request): void
    {
        $this->requireModule('documents');
        $type = (string) ($_GET['type'] ?? 'all');
        if (!in_array($type, PortalDocument::types(), true)) {
            $type = 'all';
        }
        $signature = (string) ($_GET['signature'] ?? 'all');
        if (!in_array($signature, ['all', 'pending', 'signed', 'none', 'declined'], true)) {
            $signature = 'all';
        }
        $created = (string) ($_GET['created'] ?? 'all');
        if (!in_array($created, ['all', 'today', 'week', 'month'], true)) {
            $created = 'all';
        }
        $page = $this->page();
        $scope = $this->ownerScope();
        $assigned = (int) ($_GET['assigned'] ?? 0);
        $ownerFilter = $scope;
        if ($scope === null && $assigned > 0) {
            $ownerFilter = $assigned;
        }
        $accountId = (int) ($_GET['account'] ?? 0);
        $result = PortalDocument::paginate($type, [
            'q' => $this->q(),
            'account_id' => $accountId,
            'signature' => $signature,
            'created' => $created,
            'owner_id' => $ownerFilter,
        ], $page, 20);
        view('documents/index', [
            'title' => 'Documents',
            'type' => $type,
            'counts' => PortalDocument::tabCounts($ownerFilter),
            'rows' => $result['rows'],
            'total' => $result['total'],
            'page' => $page,
            'pages' => max(1, (int) ceil($result['total'] / 20)),
            'q' => $this->q(),
            'signature' => $signature,
            'created' => $created,
            'assigned' => $assigned,
            'showAssigned' => $scope === null,
            'accountId' => $accountId,
            'accounts' => Account::allForSelect(),
            'owners' => User::salespeople((int) Auth::instance()->tenantId()),
            'notifications' => $this->notifications(),
        ]);
    }

    public function store(Request $request): void
    {
        $this->requireModule('documents');
        $this->verifyCsrf($request);
        $data = $request->all();
        $v = (new Validator())->required($data, ['account_id' => 'Account', 'title' => 'Title']);
        if ($v->fails()) {
            $this->fail($v);
        }
        $account = Account::find((int) $data['account_id']);
        if (!$account) {
            json_out(['ok' => false, 'error' => 'Account not found.'], 404);
        }
        try {
            $file = $_FILES['pdf'] ?? [];
            $name = DocumentStore::accept(is_array($file) ? $file : []);
        } catch (\RuntimeException $e) {
            json_out(['ok' => false, 'error' => $e->getMessage()], 422);
        }
        $id = PortalDocument::create([
            'account_id' => (int) $account['id'],
            'owner_id' => (int) Auth::instance()->id(),
            'related_type' => 'file',
            'related_id' => null,
            'title' => mb_substr((string) $data['title'], 0, 180),
            'kind' => 'file',
            'body' => mb_substr((string) ($data['body'] ?? ''), 0, 2000),
            'file_name' => $name,
            'shared' => 1,
        ]);
        try {
            DocumentStore::save($id, (string) $file['tmp_name']);
        } catch (\RuntimeException $e) {
            json_out(['ok' => false, 'error' => $e->getMessage()], 500);
        }
        RecordService::logActivity('note', 'PDF shared with customer', (string) $data['title'], 'account', (int) $account['id']);
        AuditLog::write('document.share', 'portal_document', $id);
        json_out(['ok' => true, 'message' => 'PDF shared on the Customer Portal.', 'redirect' => url('documents') . '?type=others']);
    }

    public function file(Request $request): void
    {
        $this->requireModule('documents');
        $row = PortalDocument::find((int) $request->param('id'));
        if (!$row) {
            http_response_code(404);
            echo 'Not found.';
            return;
        }
        $tid = (int) Auth::instance()->tenantId();
        if (!DocumentStore::exists($tid, (int) $row['id'])) {
            http_response_code(404);
            echo 'No PDF on this paper.';
            return;
        }
        DocumentStore::stream($tid, (int) $row['id'], (string) ($row['file_name'] ?? 'document.pdf'));
    }

    public function signed(Request $request): void
    {
        $this->requireModule('documents');
        $row = PortalDocument::find((int) $request->param('id'));
        if (!$row) {
            http_response_code(404);
            echo 'Not found.';
            return;
        }
        $sig = Signature::forDocument((int) $row['id']);
        if (!$sig || ($sig['status'] ?? '') !== 'signed' || empty($sig['signed_file_name'])) {
            http_response_code(404);
            echo 'No signed PDF yet.';
            return;
        }
        $tid = (int) Auth::instance()->tenantId();
        if (!DocumentStore::exists($tid, (int) $row['id'], true)) {
            http_response_code(404);
            echo 'No signed PDF yet.';
            return;
        }
        DocumentStore::stream($tid, (int) $row['id'], (string) $sig['signed_file_name'], true);
    }
}
