<?php

namespace Modules\Operations\Services;

use App\Models\ActivityLogModel;
use App\Models\CompanyModel;
use App\Models\EmployeeModel;
use App\Models\FsCustomerSignatureModel;
use App\Models\FsInspectionReportModel;
use App\Models\FsServiceVisitModel;
use App\Models\FsTechnicianJobModel;
use App\Models\WorkOrderModel;

class FieldServiceService
{
    protected FsServiceVisitModel $visits;
    protected FsTechnicianJobModel $jobs;
    protected FsInspectionReportModel $reports;
    protected FsCustomerSignatureModel $signatures;
    protected EmployeeModel $employees;
    protected CompanyModel $companies;
    protected WorkOrderModel $workOrders;
    protected ActivityLogModel $activity;

    public function __construct()
    {
        $this->visits     = new FsServiceVisitModel();
        $this->jobs       = new FsTechnicianJobModel();
        $this->reports    = new FsInspectionReportModel();
        $this->signatures = new FsCustomerSignatureModel();
        $this->employees  = new EmployeeModel();
        $this->companies  = new CompanyModel();
        $this->workOrders = new WorkOrderModel();
        $this->activity   = new ActivityLogModel();
    }

    // ------------------------------------------------------------------ Visits

    public function createVisit(array $input, ?int $actingUserId): array
    {
        $title = trim((string) ($input['title'] ?? ''));
        if ($title === '') {
            return ['success' => false, 'errors' => ['title' => 'Title is required.']];
        }

        $priority = (string) ($input['priority'] ?? 'normal');
        if (! in_array($priority, FsServiceVisitModel::PRIORITIES, true)) {
            $priority = 'normal';
        }

        $status = (string) ($input['status'] ?? 'draft');
        if (! in_array($status, ['draft', 'scheduled'], true)) {
            $status = 'draft';
        }

        $technicianId = $this->resolveActiveEmployeeId($input['technician_employee_id'] ?? null);
        if ($technicianId === false) {
            return ['success' => false, 'errors' => ['technician_employee_id' => 'Select an active employee.']];
        }

        $companyId = $this->resolveCompanyId($input['company_id'] ?? null);
        if ($companyId === false) {
            return ['success' => false, 'errors' => ['company_id' => 'Select a valid company.']];
        }

        $workOrderId = $this->resolveWorkOrderId($input['work_order_id'] ?? null);
        if ($workOrderId === false) {
            return ['success' => false, 'errors' => ['work_order_id' => 'Select a valid work order.']];
        }

        $data = [
            'number'                 => $this->visits->nextNumber(),
            'title'                  => $title,
            'description'            => trim((string) ($input['description'] ?? '')) ?: null,
            'company_id'             => $companyId,
            'work_order_id'          => $workOrderId,
            'technician_employee_id' => $technicianId,
            'priority'               => $priority,
            'status'                 => $status,
            'location'               => trim((string) ($input['location'] ?? '')) ?: null,
            'scheduled_date'         => $this->nullableDate($input['scheduled_date'] ?? null),
            'scheduled_start'        => $this->nullableDate($input['scheduled_start'] ?? null),
            'scheduled_end'          => $this->nullableDate($input['scheduled_end'] ?? null),
            'notes'                  => trim((string) ($input['notes'] ?? '')) ?: null,
            'created_by'             => $actingUserId,
            'updated_by'             => $actingUserId,
        ];

        if (! $this->visits->insert($data, true)) {
            return ['success' => false, 'errors' => $this->visits->errors()];
        }

        $id = (int) $this->visits->getInsertID();
        $this->activity->log('field_service', 'visit_created', $actingUserId, "Created service visit #{$id} ({$data['number']})", (string) $id);

        return ['success' => true, 'id' => $id];
    }

    public function updateVisit(int $id, array $input, ?int $actingUserId): array
    {
        $visit = $this->visits->find($id);
        if (! $visit) {
            return ['success' => false, 'errors' => ['id' => 'Service visit not found.']];
        }

        if (! in_array($visit['status'], FsServiceVisitModel::OPEN_STATUSES, true)) {
            return ['success' => false, 'errors' => ['status' => 'Only open visits can be edited.']];
        }

        $title = trim((string) ($input['title'] ?? ''));
        if ($title === '') {
            return ['success' => false, 'errors' => ['title' => 'Title is required.']];
        }

        $priority = (string) ($input['priority'] ?? $visit['priority']);
        if (! in_array($priority, FsServiceVisitModel::PRIORITIES, true)) {
            $priority = $visit['priority'];
        }

        $status = (string) ($input['status'] ?? $visit['status']);
        if (! in_array($status, FsServiceVisitModel::OPEN_STATUSES, true)) {
            $status = $visit['status'];
        }

        $technicianId = $this->resolveActiveEmployeeId($input['technician_employee_id'] ?? null);
        if ($technicianId === false) {
            return ['success' => false, 'errors' => ['technician_employee_id' => 'Select an active employee.']];
        }

        $companyId = $this->resolveCompanyId($input['company_id'] ?? null);
        if ($companyId === false) {
            return ['success' => false, 'errors' => ['company_id' => 'Select a valid company.']];
        }

        $workOrderId = $this->resolveWorkOrderId($input['work_order_id'] ?? null);
        if ($workOrderId === false) {
            return ['success' => false, 'errors' => ['work_order_id' => 'Select a valid work order.']];
        }

        $data = [
            'title'                  => $title,
            'description'            => trim((string) ($input['description'] ?? '')) ?: null,
            'company_id'             => $companyId,
            'work_order_id'          => $workOrderId,
            'technician_employee_id' => $technicianId,
            'priority'               => $priority,
            'status'                 => $status,
            'location'               => trim((string) ($input['location'] ?? '')) ?: null,
            'scheduled_date'         => $this->nullableDate($input['scheduled_date'] ?? null),
            'scheduled_start'        => $this->nullableDate($input['scheduled_start'] ?? null),
            'scheduled_end'          => $this->nullableDate($input['scheduled_end'] ?? null),
            'notes'                  => trim((string) ($input['notes'] ?? '')) ?: null,
            'updated_by'             => $actingUserId,
        ];

        if (! $this->visits->update($id, $data)) {
            return ['success' => false, 'errors' => $this->visits->errors()];
        }

        $this->activity->log('field_service', 'visit_updated', $actingUserId, "Updated service visit #{$id}", (string) $id);

        return ['success' => true];
    }

    public function markVisitEnRoute(int $id, ?int $actingUserId): array
    {
        $visit = $this->visits->find($id);
        if (! $visit) {
            return ['success' => false, 'error' => 'Service visit not found.'];
        }

        if (! in_array($visit['status'], ['draft', 'scheduled'], true)) {
            return ['success' => false, 'error' => 'Only draft or scheduled visits can be marked en route.'];
        }

        $this->visits->update($id, [
            'status'     => 'en_route',
            'updated_by' => $actingUserId,
        ]);
        $this->activity->log('field_service', 'visit_en_route', $actingUserId, "Marked visit #{$id} en route", (string) $id);

        return ['success' => true];
    }

    public function markVisitOnSite(int $id, ?int $actingUserId): array
    {
        $visit = $this->visits->find($id);
        if (! $visit) {
            return ['success' => false, 'error' => 'Service visit not found.'];
        }

        if (! in_array($visit['status'], ['scheduled', 'en_route'], true)) {
            return ['success' => false, 'error' => 'Only scheduled or en-route visits can be marked on site.'];
        }

        $this->visits->update($id, [
            'status'     => 'on_site',
            'arrived_at' => date('Y-m-d H:i:s'),
            'updated_by' => $actingUserId,
        ]);
        $this->activity->log('field_service', 'visit_on_site', $actingUserId, "Marked visit #{$id} on site", (string) $id);

        return ['success' => true];
    }

    public function completeVisit(int $id, ?int $actingUserId): array
    {
        $visit = $this->visits->find($id);
        if (! $visit) {
            return ['success' => false, 'error' => 'Service visit not found.'];
        }

        if (! in_array($visit['status'], FsServiceVisitModel::OPEN_STATUSES, true)) {
            return ['success' => false, 'error' => 'Only open visits can be completed.'];
        }

        $this->visits->update($id, [
            'status'       => 'completed',
            'completed_at' => date('Y-m-d H:i:s'),
            'updated_by'   => $actingUserId,
        ]);
        $this->activity->log('field_service', 'visit_completed', $actingUserId, "Completed visit #{$id}", (string) $id);

        return ['success' => true];
    }

    public function cancelVisit(int $id, ?int $actingUserId): array
    {
        $visit = $this->visits->find($id);
        if (! $visit) {
            return ['success' => false, 'error' => 'Service visit not found.'];
        }

        if (! in_array($visit['status'], FsServiceVisitModel::OPEN_STATUSES, true)) {
            return ['success' => false, 'error' => 'Only open visits can be cancelled.'];
        }

        $this->visits->update($id, [
            'status'     => 'cancelled',
            'updated_by' => $actingUserId,
        ]);
        $this->activity->log('field_service', 'visit_cancelled', $actingUserId, "Cancelled visit #{$id}", (string) $id);

        return ['success' => true];
    }

    public function deleteVisit(int $id, ?int $actingUserId): array
    {
        $visit = $this->visits->find($id);
        if (! $visit) {
            return ['success' => false, 'error' => 'Service visit not found.'];
        }

        if (! in_array($visit['status'], ['draft', 'cancelled'], true)) {
            return ['success' => false, 'error' => 'Only draft or cancelled visits can be deleted.'];
        }

        $this->visits->delete($id);
        $this->activity->log('field_service', 'visit_deleted', $actingUserId, "Deleted visit #{$id}", (string) $id);

        return ['success' => true];
    }

    // -------------------------------------------------------------------- Jobs

    public function createJob(array $input, ?int $actingUserId): array
    {
        $title = trim((string) ($input['title'] ?? ''));
        if ($title === '') {
            return ['success' => false, 'errors' => ['title' => 'Title is required.']];
        }

        $employeeId = (int) ($input['employee_id'] ?? 0);
        if ($employeeId <= 0) {
            return ['success' => false, 'errors' => ['employee_id' => 'Technician is required.']];
        }
        $employee = $this->employees->find($employeeId);
        if (! $employee || ($employee['status'] ?? '') !== 'active') {
            return ['success' => false, 'errors' => ['employee_id' => 'Select an active employee.']];
        }

        $priority = (string) ($input['priority'] ?? 'normal');
        if (! in_array($priority, FsTechnicianJobModel::PRIORITIES, true)) {
            $priority = 'normal';
        }

        $status = (string) ($input['status'] ?? 'assigned');
        if (! in_array($status, ['assigned', 'accepted'], true)) {
            $status = 'assigned';
        }

        $visitId = $this->resolveVisitId($input['service_visit_id'] ?? null);
        if ($visitId === false) {
            return ['success' => false, 'errors' => ['service_visit_id' => 'Select a valid service visit.']];
        }

        $data = [
            'number'           => $this->jobs->nextNumber(),
            'service_visit_id' => $visitId,
            'employee_id'      => $employeeId,
            'title'            => $title,
            'role'             => trim((string) ($input['role'] ?? '')) ?: null,
            'status'           => $status,
            'priority'         => $priority,
            'due_date'         => $this->nullableDate($input['due_date'] ?? null),
            'assigned_at'      => date('Y-m-d H:i:s'),
            'notes'            => trim((string) ($input['notes'] ?? '')) ?: null,
            'assigned_by'      => $actingUserId,
            'created_by'       => $actingUserId,
            'updated_by'       => $actingUserId,
        ];

        if (! $this->jobs->insert($data, true)) {
            return ['success' => false, 'errors' => $this->jobs->errors()];
        }

        $id = (int) $this->jobs->getInsertID();
        $this->activity->log('field_service', 'job_created', $actingUserId, "Created technician job #{$id} ({$data['number']})", (string) $id);

        return ['success' => true, 'id' => $id];
    }

    public function updateJob(int $id, array $input, ?int $actingUserId): array
    {
        $job = $this->jobs->find($id);
        if (! $job) {
            return ['success' => false, 'errors' => ['id' => 'Technician job not found.']];
        }

        if (! in_array($job['status'], FsTechnicianJobModel::OPEN_STATUSES, true)) {
            return ['success' => false, 'errors' => ['status' => 'Only open jobs can be edited.']];
        }

        $title = trim((string) ($input['title'] ?? ''));
        if ($title === '') {
            return ['success' => false, 'errors' => ['title' => 'Title is required.']];
        }

        $employeeId = (int) ($input['employee_id'] ?? 0);
        if ($employeeId <= 0) {
            return ['success' => false, 'errors' => ['employee_id' => 'Technician is required.']];
        }
        $employee = $this->employees->find($employeeId);
        if (! $employee || ($employee['status'] ?? '') !== 'active') {
            return ['success' => false, 'errors' => ['employee_id' => 'Select an active employee.']];
        }

        $priority = (string) ($input['priority'] ?? $job['priority']);
        if (! in_array($priority, FsTechnicianJobModel::PRIORITIES, true)) {
            $priority = $job['priority'];
        }

        $status = (string) ($input['status'] ?? $job['status']);
        if (! in_array($status, FsTechnicianJobModel::OPEN_STATUSES, true)) {
            $status = $job['status'];
        }

        $visitId = $this->resolveVisitId($input['service_visit_id'] ?? null);
        if ($visitId === false) {
            return ['success' => false, 'errors' => ['service_visit_id' => 'Select a valid service visit.']];
        }

        $data = [
            'service_visit_id' => $visitId,
            'employee_id'      => $employeeId,
            'title'            => $title,
            'role'             => trim((string) ($input['role'] ?? '')) ?: null,
            'status'           => $status,
            'priority'         => $priority,
            'due_date'         => $this->nullableDate($input['due_date'] ?? null),
            'notes'            => trim((string) ($input['notes'] ?? '')) ?: null,
            'updated_by'       => $actingUserId,
        ];

        if (! $this->jobs->update($id, $data)) {
            return ['success' => false, 'errors' => $this->jobs->errors()];
        }

        $this->activity->log('field_service', 'job_updated', $actingUserId, "Updated technician job #{$id}", (string) $id);

        return ['success' => true];
    }

    public function startJob(int $id, ?int $actingUserId): array
    {
        $job = $this->jobs->find($id);
        if (! $job) {
            return ['success' => false, 'error' => 'Technician job not found.'];
        }

        if (! in_array($job['status'], ['assigned', 'accepted'], true)) {
            return ['success' => false, 'error' => 'Only assigned or accepted jobs can be started.'];
        }

        $this->jobs->update($id, [
            'status'     => 'in_progress',
            'started_at' => date('Y-m-d H:i:s'),
            'updated_by' => $actingUserId,
        ]);
        $this->activity->log('field_service', 'job_started', $actingUserId, "Started technician job #{$id}", (string) $id);

        return ['success' => true];
    }

    public function completeJob(int $id, ?int $actingUserId): array
    {
        $job = $this->jobs->find($id);
        if (! $job) {
            return ['success' => false, 'error' => 'Technician job not found.'];
        }

        if (! in_array($job['status'], FsTechnicianJobModel::OPEN_STATUSES, true)) {
            return ['success' => false, 'error' => 'Only open jobs can be completed.'];
        }

        $this->jobs->update($id, [
            'status'       => 'done',
            'completed_at' => date('Y-m-d H:i:s'),
            'updated_by'   => $actingUserId,
        ]);
        $this->activity->log('field_service', 'job_completed', $actingUserId, "Completed technician job #{$id}", (string) $id);

        return ['success' => true];
    }

    public function cancelJob(int $id, ?int $actingUserId): array
    {
        $job = $this->jobs->find($id);
        if (! $job) {
            return ['success' => false, 'error' => 'Technician job not found.'];
        }

        if (! in_array($job['status'], FsTechnicianJobModel::OPEN_STATUSES, true)) {
            return ['success' => false, 'error' => 'Only open jobs can be cancelled.'];
        }

        $this->jobs->update($id, [
            'status'     => 'cancelled',
            'updated_by' => $actingUserId,
        ]);
        $this->activity->log('field_service', 'job_cancelled', $actingUserId, "Cancelled technician job #{$id}", (string) $id);

        return ['success' => true];
    }

    public function deleteJob(int $id, ?int $actingUserId): array
    {
        $job = $this->jobs->find($id);
        if (! $job) {
            return ['success' => false, 'error' => 'Technician job not found.'];
        }

        if (! in_array($job['status'], ['assigned', 'cancelled'], true)) {
            return ['success' => false, 'error' => 'Only assigned or cancelled jobs can be deleted.'];
        }

        $this->jobs->delete($id);
        $this->activity->log('field_service', 'job_deleted', $actingUserId, "Deleted technician job #{$id}", (string) $id);

        return ['success' => true];
    }

    // ---------------------------------------------------------------- Reports

    public function createReport(array $input, ?int $actingUserId): array
    {
        $title = trim((string) ($input['title'] ?? ''));
        if ($title === '') {
            return ['success' => false, 'errors' => ['title' => 'Title is required.']];
        }

        $result = (string) ($input['result'] ?? 'pending');
        if (! in_array($result, FsInspectionReportModel::RESULTS, true)) {
            $result = 'pending';
        }

        $inspectorId = $this->resolveActiveEmployeeId($input['inspector_employee_id'] ?? null);
        if ($inspectorId === false) {
            return ['success' => false, 'errors' => ['inspector_employee_id' => 'Select an active employee.']];
        }

        $visitId = $this->resolveVisitId($input['service_visit_id'] ?? null);
        if ($visitId === false) {
            return ['success' => false, 'errors' => ['service_visit_id' => 'Select a valid service visit.']];
        }

        $workOrderId = $this->resolveWorkOrderId($input['work_order_id'] ?? null);
        if ($workOrderId === false) {
            return ['success' => false, 'errors' => ['work_order_id' => 'Select a valid work order.']];
        }

        $data = [
            'number'                => $this->reports->nextNumber(),
            'service_visit_id'      => $visitId,
            'work_order_id'         => $workOrderId,
            'inspector_employee_id' => $inspectorId,
            'title'                 => $title,
            'findings'              => trim((string) ($input['findings'] ?? '')) ?: null,
            'result'                => $result,
            'status'                => 'draft',
            'inspected_at'          => $this->nullableDate($input['inspected_at'] ?? null),
            'notes'                 => trim((string) ($input['notes'] ?? '')) ?: null,
            'created_by'            => $actingUserId,
            'updated_by'            => $actingUserId,
        ];

        if (! $this->reports->insert($data, true)) {
            return ['success' => false, 'errors' => $this->reports->errors()];
        }

        $id = (int) $this->reports->getInsertID();
        $this->activity->log('field_service', 'report_created', $actingUserId, "Created inspection report #{$id} ({$data['number']})", (string) $id);

        return ['success' => true, 'id' => $id];
    }

    public function updateReport(int $id, array $input, ?int $actingUserId): array
    {
        $report = $this->reports->find($id);
        if (! $report) {
            return ['success' => false, 'errors' => ['id' => 'Inspection report not found.']];
        }

        if (! in_array($report['status'], FsInspectionReportModel::OPEN_STATUSES, true)) {
            return ['success' => false, 'errors' => ['status' => 'Only draft or rejected reports can be edited.']];
        }

        $title = trim((string) ($input['title'] ?? ''));
        if ($title === '') {
            return ['success' => false, 'errors' => ['title' => 'Title is required.']];
        }

        $result = (string) ($input['result'] ?? $report['result']);
        if (! in_array($result, FsInspectionReportModel::RESULTS, true)) {
            $result = $report['result'];
        }

        $inspectorId = $this->resolveActiveEmployeeId($input['inspector_employee_id'] ?? null);
        if ($inspectorId === false) {
            return ['success' => false, 'errors' => ['inspector_employee_id' => 'Select an active employee.']];
        }

        $visitId = $this->resolveVisitId($input['service_visit_id'] ?? null);
        if ($visitId === false) {
            return ['success' => false, 'errors' => ['service_visit_id' => 'Select a valid service visit.']];
        }

        $workOrderId = $this->resolveWorkOrderId($input['work_order_id'] ?? null);
        if ($workOrderId === false) {
            return ['success' => false, 'errors' => ['work_order_id' => 'Select a valid work order.']];
        }

        $data = [
            'service_visit_id'      => $visitId,
            'work_order_id'         => $workOrderId,
            'inspector_employee_id' => $inspectorId,
            'title'                 => $title,
            'findings'              => trim((string) ($input['findings'] ?? '')) ?: null,
            'result'                => $result,
            'status'                => 'draft',
            'inspected_at'          => $this->nullableDate($input['inspected_at'] ?? null),
            'notes'                 => trim((string) ($input['notes'] ?? '')) ?: null,
            'updated_by'            => $actingUserId,
        ];

        if (! $this->reports->update($id, $data)) {
            return ['success' => false, 'errors' => $this->reports->errors()];
        }

        $this->activity->log('field_service', 'report_updated', $actingUserId, "Updated inspection report #{$id}", (string) $id);

        return ['success' => true];
    }

    public function submitReport(int $id, ?int $actingUserId): array
    {
        $report = $this->reports->find($id);
        if (! $report) {
            return ['success' => false, 'error' => 'Inspection report not found.'];
        }

        if (! in_array($report['status'], FsInspectionReportModel::OPEN_STATUSES, true)) {
            return ['success' => false, 'error' => 'Only draft or rejected reports can be submitted.'];
        }

        $this->reports->update($id, [
            'status'     => 'submitted',
            'updated_by' => $actingUserId,
        ]);
        $this->activity->log('field_service', 'report_submitted', $actingUserId, "Submitted inspection report #{$id}", (string) $id);

        return ['success' => true];
    }

    public function approveReport(int $id, ?int $actingUserId): array
    {
        $report = $this->reports->find($id);
        if (! $report) {
            return ['success' => false, 'error' => 'Inspection report not found.'];
        }

        if ($report['status'] !== 'submitted') {
            return ['success' => false, 'error' => 'Only submitted reports can be approved.'];
        }

        $this->reports->update($id, [
            'status'     => 'approved',
            'updated_by' => $actingUserId,
        ]);
        $this->activity->log('field_service', 'report_approved', $actingUserId, "Approved inspection report #{$id}", (string) $id);

        return ['success' => true];
    }

    public function rejectReport(int $id, ?int $actingUserId): array
    {
        $report = $this->reports->find($id);
        if (! $report) {
            return ['success' => false, 'error' => 'Inspection report not found.'];
        }

        if ($report['status'] !== 'submitted') {
            return ['success' => false, 'error' => 'Only submitted reports can be rejected.'];
        }

        $this->reports->update($id, [
            'status'     => 'rejected',
            'updated_by' => $actingUserId,
        ]);
        $this->activity->log('field_service', 'report_rejected', $actingUserId, "Rejected inspection report #{$id}", (string) $id);

        return ['success' => true];
    }

    public function deleteReport(int $id, ?int $actingUserId): array
    {
        $report = $this->reports->find($id);
        if (! $report) {
            return ['success' => false, 'error' => 'Inspection report not found.'];
        }

        if (! in_array($report['status'], ['draft', 'rejected'], true)) {
            return ['success' => false, 'error' => 'Only draft or rejected reports can be deleted.'];
        }

        $this->reports->delete($id);
        $this->activity->log('field_service', 'report_deleted', $actingUserId, "Deleted inspection report #{$id}", (string) $id);

        return ['success' => true];
    }

    // ------------------------------------------------------------ Signatures

    public function createSignature(array $input, ?int $actingUserId): array
    {
        $signerName = trim((string) ($input['signer_name'] ?? ''));
        if ($signerName === '') {
            return ['success' => false, 'errors' => ['signer_name' => 'Signer name is required.']];
        }

        $companyId = $this->resolveCompanyId($input['company_id'] ?? null);
        if ($companyId === false) {
            return ['success' => false, 'errors' => ['company_id' => 'Select a valid company.']];
        }

        $visitId = $this->resolveVisitId($input['service_visit_id'] ?? null);
        if ($visitId === false) {
            return ['success' => false, 'errors' => ['service_visit_id' => 'Select a valid service visit.']];
        }

        $reportId = $this->resolveReportId($input['inspection_report_id'] ?? null);
        if ($reportId === false) {
            return ['success' => false, 'errors' => ['inspection_report_id' => 'Select a valid inspection report.']];
        }

        $data = [
            'number'               => $this->signatures->nextNumber(),
            'service_visit_id'     => $visitId,
            'inspection_report_id' => $reportId,
            'company_id'           => $companyId,
            'signer_name'          => $signerName,
            'signer_title'         => trim((string) ($input['signer_title'] ?? '')) ?: null,
            'signature_notes'      => trim((string) ($input['signature_notes'] ?? '')) ?: null,
            'signed_at'            => $this->nullableDate($input['signed_at'] ?? null) ?: date('Y-m-d H:i:s'),
            'status'               => 'captured',
            'captured_by'          => $actingUserId,
            'created_by'           => $actingUserId,
            'updated_by'           => $actingUserId,
        ];

        if (! $this->signatures->insert($data, true)) {
            return ['success' => false, 'errors' => $this->signatures->errors()];
        }

        $id = (int) $this->signatures->getInsertID();
        $this->activity->log('field_service', 'signature_created', $actingUserId, "Captured signature #{$id} ({$data['number']})", (string) $id);

        return ['success' => true, 'id' => $id];
    }

    public function updateSignature(int $id, array $input, ?int $actingUserId): array
    {
        $signature = $this->signatures->find($id);
        if (! $signature) {
            return ['success' => false, 'errors' => ['id' => 'Customer signature not found.']];
        }

        if ($signature['status'] !== 'captured') {
            return ['success' => false, 'errors' => ['status' => 'Only captured signatures can be edited.']];
        }

        $signerName = trim((string) ($input['signer_name'] ?? ''));
        if ($signerName === '') {
            return ['success' => false, 'errors' => ['signer_name' => 'Signer name is required.']];
        }

        $companyId = $this->resolveCompanyId($input['company_id'] ?? null);
        if ($companyId === false) {
            return ['success' => false, 'errors' => ['company_id' => 'Select a valid company.']];
        }

        $visitId = $this->resolveVisitId($input['service_visit_id'] ?? null);
        if ($visitId === false) {
            return ['success' => false, 'errors' => ['service_visit_id' => 'Select a valid service visit.']];
        }

        $reportId = $this->resolveReportId($input['inspection_report_id'] ?? null);
        if ($reportId === false) {
            return ['success' => false, 'errors' => ['inspection_report_id' => 'Select a valid inspection report.']];
        }

        $data = [
            'service_visit_id'     => $visitId,
            'inspection_report_id' => $reportId,
            'company_id'           => $companyId,
            'signer_name'          => $signerName,
            'signer_title'         => trim((string) ($input['signer_title'] ?? '')) ?: null,
            'signature_notes'      => trim((string) ($input['signature_notes'] ?? '')) ?: null,
            'signed_at'            => $this->nullableDate($input['signed_at'] ?? null),
            'updated_by'           => $actingUserId,
        ];

        if (! $this->signatures->update($id, $data)) {
            return ['success' => false, 'errors' => $this->signatures->errors()];
        }

        $this->activity->log('field_service', 'signature_updated', $actingUserId, "Updated signature #{$id}", (string) $id);

        return ['success' => true];
    }

    public function voidSignature(int $id, ?int $actingUserId): array
    {
        $signature = $this->signatures->find($id);
        if (! $signature) {
            return ['success' => false, 'error' => 'Customer signature not found.'];
        }

        if ($signature['status'] !== 'captured') {
            return ['success' => false, 'error' => 'Only captured signatures can be voided.'];
        }

        $this->signatures->update($id, [
            'status'     => 'voided',
            'updated_by' => $actingUserId,
        ]);
        $this->activity->log('field_service', 'signature_voided', $actingUserId, "Voided signature #{$id}", (string) $id);

        return ['success' => true];
    }

    public function deleteSignature(int $id, ?int $actingUserId): array
    {
        $signature = $this->signatures->find($id);
        if (! $signature) {
            return ['success' => false, 'error' => 'Customer signature not found.'];
        }

        if (! in_array($signature['status'], ['captured', 'voided'], true)) {
            return ['success' => false, 'error' => 'Signature cannot be deleted.'];
        }

        $this->signatures->delete($id);
        $this->activity->log('field_service', 'signature_deleted', $actingUserId, "Deleted signature #{$id}", (string) $id);

        return ['success' => true];
    }

    // --------------------------------------------------------------- Helpers

    /**
     * @return int|null|false null when empty, int when valid, false when invalid
     */
    protected function resolveActiveEmployeeId(mixed $value): int|null|false
    {
        $id = (int) $value;
        if ($id <= 0) {
            return null;
        }

        $employee = $this->employees->find($id);
        if (! $employee || ($employee['status'] ?? '') !== 'active') {
            return false;
        }

        return $id;
    }

    /**
     * @return int|null|false
     */
    protected function resolveCompanyId(mixed $value): int|null|false
    {
        $id = (int) $value;
        if ($id <= 0) {
            return null;
        }

        if (! $this->companies->find($id)) {
            return false;
        }

        return $id;
    }

    /**
     * @return int|null|false
     */
    protected function resolveWorkOrderId(mixed $value): int|null|false
    {
        $id = (int) $value;
        if ($id <= 0) {
            return null;
        }

        if (! $this->workOrders->find($id)) {
            return false;
        }

        return $id;
    }

    /**
     * @return int|null|false
     */
    protected function resolveVisitId(mixed $value): int|null|false
    {
        $id = (int) $value;
        if ($id <= 0) {
            return null;
        }

        if (! $this->visits->find($id)) {
            return false;
        }

        return $id;
    }

    /**
     * @return int|null|false
     */
    protected function resolveReportId(mixed $value): int|null|false
    {
        $id = (int) $value;
        if ($id <= 0) {
            return null;
        }

        if (! $this->reports->find($id)) {
            return false;
        }

        return $id;
    }

    protected function nullableDate(mixed $value): ?string
    {
        $value = trim((string) $value);
        if ($value === '') {
            return null;
        }

        $value = str_replace('T', ' ', $value);
        if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}$/', $value)) {
            $value .= ':00';
        }

        return $value;
    }
}
