<?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\Activity;
use App\Models\AuditLog;
use App\Models\Contact;
use App\Models\Lead;
use App\Models\Opportunity;
use App\Services\DocumentStore;
use App\Services\RecordService;

final class ActivityController extends BaseController
{
    public function store(Request $request): void
    {
        $this->requireModule('tasks');
        $this->verifyCsrf($request);
        $data = $request->all();
        $type = $data['type'] ?? 'note';
        if (!in_array($type, ['call', 'email', 'meeting', 'visit', 'note'], true)) {
            $type = 'note';
        }
        $v = (new Validator())->required($data, ['subject' => 'Subject']);
        if ($v->fails()) {
            $this->fail($v);
        }
        $relatedType = trim((string) ($data['related_type'] ?? ''));
        $relatedId = (int) ($data['related_id'] ?? 0);
        $allowed = ['lead', 'opportunity', 'account', 'contact'];
        if ($relatedType !== '' && !in_array($relatedType, $allowed, true)) {
            json_out(['ok' => false, 'error' => 'A note can be on a lead, deal, or account.'], 422);
        }
        if (in_array($type, ['note', 'call'], true) && ($relatedType === '' || $relatedId < 1)) {
            json_out(['ok' => false, 'error' => 'Pick which lead, deal, or account this is for.'], 422);
        }
        if ($relatedType !== '' && $relatedId < 1) {
            json_out(['ok' => false, 'error' => 'Pick which lead, deal, or account this is for.'], 422);
        }
        if ($relatedType !== '' && $relatedId > 0) {
            $found = match ($relatedType) {
                'lead' => Lead::find($relatedId),
                'opportunity' => Opportunity::find($relatedId),
                'account' => Account::find($relatedId),
                'contact' => Contact::find($relatedId),
                default => null,
            };
            if (!$found) {
                json_out(['ok' => false, 'error' => 'That record was not found.'], 404);
            }
        } else {
            $relatedType = '';
            $relatedId = 0;
        }

        $file = $_FILES['file'] ?? [];
        $fileName = null;
        if (is_array($file) && (int) ($file['error'] ?? UPLOAD_ERR_NO_FILE) !== UPLOAD_ERR_NO_FILE) {
            try {
                $fileName = DocumentStore::acceptAttachment($file);
            } catch (\RuntimeException $e) {
                json_out(['ok' => false, 'error' => $e->getMessage()], 422);
            }
        }

        $id = RecordService::logActivity(
            $type,
            $data['subject'],
            $data['body'] ?? null,
            $relatedType !== '' ? $relatedType : null,
            $relatedId > 0 ? $relatedId : null
        );
        if ($fileName) {
            try {
                DocumentStore::saveAttachment('activity', $id, (string) $file['tmp_name'], $fileName);
                Activity::update($id, ['file_name' => $fileName]);
            } catch (\RuntimeException $e) {
                json_out(['ok' => false, 'error' => $e->getMessage()], 500);
            }
        }
        AuditLog::write('activity.create', 'activity', $id, ['type' => $type]);
        $out = ['ok' => true, 'id' => $id, 'message' => $type === 'note' ? 'Note saved.' : 'Saved.'];
        $href = related_url($relatedType !== '' ? $relatedType : null, $relatedId > 0 ? $relatedId : null);
        if ($href !== '#' && !str_ends_with($href, '#')) {
            $out['redirect'] = $href;
        }
        json_out($out);
    }

    public function file(Request $request): void
    {
        $this->requireModule('tasks');
        $id = (int) $request->param('id');
        $row = Activity::find($id);
        if (!$row || empty($row['file_name'])) {
            http_response_code(404);
            echo 'Not found.';
            return;
        }
        $scope = $this->ownerScope();
        if ($scope && (int) $row['owner_id'] !== $scope) {
            http_response_code(403);
            echo 'You cannot open this file.';
            return;
        }
        $tid = (int) Auth::instance()->tenantId();
        if (!DocumentStore::existsAttachment($tid, 'activity', $id, (string) $row['file_name'])) {
            http_response_code(404);
            echo 'No file on this note.';
            return;
        }
        DocumentStore::streamAttachment($tid, 'activity', $id, (string) $row['file_name']);
    }
}
