<?php
require_once __DIR__ . '/core/auth.php';
$user = require_login();
$pdo = pdo();

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    json_response(['ok' => false, 'message' => 'Invalid method.'], 405);
}
validate_csrf();
$action = $_POST['action'] ?? '';

function require_existing_report(PDO $pdo, array $user): int
{
    $reportId = (int) ($_POST['report_id'] ?? 0);
    if ($reportId < 1) {
        json_response(['ok' => false, 'message' => 'Save Form 01 first to create the report master record.'], 422);
    }
    require_report_access($pdo, $user, $reportId);
    return $reportId;
}

function selected_or_fail(array $allowed, string $value, string $label): string
{
    if (!in_array($value, $allowed, true)) {
        json_response(['ok' => false, 'message' => $label . ' is invalid.'], 422);
    }
    return $value;
}

try {
    switch ($action) {
        case 'save_form1':
            $agentName = trim($_POST['agent_name'] ?? '');
            if ($agentName === '') {
                json_response(['ok' => false, 'message' => 'DB Name is required.'], 422);
            }
            if (!can_access_agent($pdo, $user, $agentName)) {
                json_response(['ok' => false, 'message' => 'Selected DB Name is not assigned to this account.'], 403);
            }

            $visitedType = selected_or_fail(visit_types(), trim($_POST['visited_type'] ?? ''), 'Visited Type');
            $visitDate = trim($_POST['date_of_visit'] ?? '');
            if ($visitDate === '' || strtotime($visitDate) === false) {
                json_response(['ok' => false, 'message' => 'Date of Visit is required.'], 422);
            }

            $payload = [
                ':date_of_visit' => date('Y-m-d H:i:s', strtotime($visitDate)),
                ':agent_name' => $agentName,
                ':accompanied_by' => trim($_POST['accompanied_by'] ?? ''),
                ':visited_type' => $visitedType,
                ':start_lat' => ($_POST['start_lat'] ?? '') !== '' ? $_POST['start_lat'] : null,
                ':start_lng' => ($_POST['start_lng'] ?? '') !== '' ? $_POST['start_lng'] : null,
            ];

            $reportId = (int) ($_POST['report_id'] ?? 0);
            if ($reportId > 0) {
                require_report_access($pdo, $user, $reportId);
                $stmt = $pdo->prepare("UPDATE visit_reports
                    SET date_of_visit = :date_of_visit,
                        agent_name = :agent_name,
                        accompanied_by = :accompanied_by,
                        visited_type = :visited_type,
                        start_lat = COALESCE(:start_lat, start_lat),
                        start_lng = COALESCE(:start_lng, start_lng),
                        updated_at = NOW()
                    WHERE id = :id");
                $payload[':id'] = $reportId;
                $stmt->execute($payload);
            } else {
                $stmt = $pdo->prepare("INSERT INTO visit_reports (
                        report_uuid, user_id, date_of_visit, agent_name, accompanied_by, visited_type,
                        started_at, start_lat, start_lng, status, created_at, updated_at
                    ) VALUES (
                        UUID(), :user_id, :date_of_visit, :agent_name, :accompanied_by, :visited_type,
                        NOW(), :start_lat, :start_lng, 'draft', NOW(), NOW()
                    )");
                $payload[':user_id'] = $user['id'];
                $stmt->execute($payload);
                $reportId = (int) $pdo->lastInsertId();
            }
            upsert_progress($pdo, $reportId, 1);
            json_response(['ok' => true, 'message' => 'Form 01 saved successfully.', 'report_id' => $reportId]);
            break;

        case 'save_form2':
            $reportId = require_existing_report($pdo, $user);
            $routeMapChoice = selected_or_fail(yes_no_options(), trim($_POST['territory_route_map'] ?? 'No'), 'Territory Route Map');
            $removeRouteMap = ($_POST['territory_route_map_remove'] ?? '0') === '1' || $routeMapChoice === 'No';
            $routeMapFile = null;

            if (!$removeRouteMap) {
                $routeMapFile = save_uploaded_file($_FILES['territory_route_map_file'] ?? [], 'route_map');
                if (!$routeMapFile) {
                    $routeMapFile = save_base64_image($_POST['webcam_route_map'] ?? '', 'route_map');
                }
                if (!$routeMapFile) {
                    $stmt = $pdo->prepare('SELECT territory_route_map_file FROM report_db_profile WHERE report_id = ?');
                    $stmt->execute([$reportId]);
                    $routeMapFile = $stmt->fetchColumn() ?: null;
                }
            }

            $stmt = $pdo->prepare("INSERT INTO report_db_profile (
                report_id, owner_contact, coverage_area, route_strength, vehicle_availability,
                log_book_updated, territory_route_map, territory_route_map_file, route_plan,
                no_credit_bills, credit_bill_total, no_cheques, cheque_total, cash_bank_total,
                progress_sheet_updated, progress_sheet_comment, sku_sales_update, sku_sales_comment,
                store_length, store_width, store_condition, market_return_condition,
                store_table_count, store_chair_count, store_comments, updated_at
            ) VALUES (
                :report_id, :owner_contact, :coverage_area, :route_strength, :vehicle_availability,
                :log_book_updated, :territory_route_map, :territory_route_map_file, :route_plan,
                :no_credit_bills, :credit_bill_total, :no_cheques, :cheque_total, :cash_bank_total,
                :progress_sheet_updated, :progress_sheet_comment, :sku_sales_update, :sku_sales_comment,
                :store_length, :store_width, :store_condition, :market_return_condition,
                :store_table_count, :store_chair_count, :store_comments, NOW()
            ) ON DUPLICATE KEY UPDATE
                owner_contact = VALUES(owner_contact),
                coverage_area = VALUES(coverage_area),
                route_strength = VALUES(route_strength),
                vehicle_availability = VALUES(vehicle_availability),
                log_book_updated = VALUES(log_book_updated),
                territory_route_map = VALUES(territory_route_map),
                territory_route_map_file = VALUES(territory_route_map_file),
                route_plan = VALUES(route_plan),
                no_credit_bills = VALUES(no_credit_bills),
                credit_bill_total = VALUES(credit_bill_total),
                no_cheques = VALUES(no_cheques),
                cheque_total = VALUES(cheque_total),
                cash_bank_total = VALUES(cash_bank_total),
                progress_sheet_updated = VALUES(progress_sheet_updated),
                progress_sheet_comment = VALUES(progress_sheet_comment),
                sku_sales_update = VALUES(sku_sales_update),
                sku_sales_comment = VALUES(sku_sales_comment),
                store_length = VALUES(store_length),
                store_width = VALUES(store_width),
                store_condition = VALUES(store_condition),
                market_return_condition = VALUES(market_return_condition),
                store_table_count = VALUES(store_table_count),
                store_chair_count = VALUES(store_chair_count),
                store_comments = VALUES(store_comments),
                updated_at = NOW()");
            $stmt->execute([
                ':report_id' => $reportId,
                ':owner_contact' => trim($_POST['owner_contact'] ?? ''),
                ':coverage_area' => trim($_POST['coverage_area'] ?? ''),
                ':route_strength' => trim($_POST['route_strength'] ?? ''),
                ':vehicle_availability' => trim($_POST['vehicle_availability'] ?? ''),
                ':log_book_updated' => selected_or_fail(yes_no_options(), trim($_POST['log_book_updated'] ?? 'No'), 'Log Book Update'),
                ':territory_route_map' => $routeMapChoice,
                ':territory_route_map_file' => $routeMapFile,
                ':route_plan' => selected_or_fail(yes_no_options(), trim($_POST['route_plan'] ?? 'No'), 'Route Plan'),
                ':no_credit_bills' => (int) ($_POST['no_credit_bills'] ?? 0),
                ':credit_bill_total' => (float) ($_POST['credit_bill_total'] ?? 0),
                ':no_cheques' => (int) ($_POST['no_cheques'] ?? 0),
                ':cheque_total' => (float) ($_POST['cheque_total'] ?? 0),
                ':cash_bank_total' => (float) ($_POST['cash_bank_total'] ?? 0),
                ':progress_sheet_updated' => selected_or_fail(yes_no_options(), trim($_POST['progress_sheet_updated'] ?? 'No'), 'Progress Sheet Update'),
                ':progress_sheet_comment' => trim($_POST['progress_sheet_comment'] ?? ''),
                ':sku_sales_update' => selected_or_fail(['Low', 'Moderate', 'High'], trim($_POST['sku_sales_update'] ?? 'Low'), 'SKU Sales Update'),
                ':sku_sales_comment' => trim($_POST['sku_sales_comment'] ?? ''),
                ':store_length' => ($_POST['store_length'] ?? '') !== '' ? (float) $_POST['store_length'] : null,
                ':store_width' => ($_POST['store_width'] ?? '') !== '' ? (float) $_POST['store_width'] : null,
                ':store_condition' => trim($_POST['store_condition'] ?? ''),
                ':market_return_condition' => trim($_POST['market_return_condition'] ?? ''),
                ':store_table_count' => (int) ($_POST['store_table_count'] ?? 0),
                ':store_chair_count' => (int) ($_POST['store_chair_count'] ?? 0),
                ':store_comments' => trim($_POST['store_comments'] ?? ''),
            ]);
            upsert_progress($pdo, $reportId, 2);
            json_response(['ok' => true, 'message' => 'Form 02 saved successfully.', 'report_id' => $reportId]);
            break;

        case 'save_form3':
            $reportId = require_existing_report($pdo, $user);
            $targets = $_POST['mtd_target'] ?? [];
            $achievements = $_POST['mtd_achievement'] ?? [];
            $pdo->beginTransaction();
            $pdo->prepare('DELETE FROM report_sales_snapshot WHERE report_id = ?')->execute([$reportId]);
            $stmt = $pdo->prepare("INSERT INTO report_sales_snapshot (report_id, category_name, mtd_target, mtd_achievement, variance, status_remarks)
                VALUES (:report_id, :category_name, :mtd_target, :mtd_achievement, :variance, :status_remarks)");
            foreach (report_categories() as $i => $category) {
                $target = (float) ($targets[$i] ?? 0);
                $achievement = (float) ($achievements[$i] ?? 0);
                $variance = $achievement - $target;
                $stmt->execute([
                    ':report_id' => $reportId,
                    ':category_name' => $category,
                    ':mtd_target' => $target,
                    ':mtd_achievement' => $achievement,
                    ':variance' => $variance,
                    ':status_remarks' => compute_sales_status($target, $achievement),
                ]);
            }
            upsert_progress($pdo, $reportId, 3);
            $pdo->commit();
            json_response(['ok' => true, 'message' => 'Form 03 saved successfully.', 'report_id' => $reportId]);
            break;

        case 'save_form4':
            $reportId = require_existing_report($pdo, $user);
            $products = $_POST['product_name'] ?? [];
            $nonEmptyCount = 0;
            foreach ($products as $name) {
                if (trim($name) !== '') {
                    $nonEmptyCount++;
                }
            }
            if ($nonEmptyCount < 10) {
                json_response(['ok' => false, 'message' => 'Please enter at least 10 products in stock status.'], 422);
            }
            $stockLevels = $_POST['stock_level'] ?? [];
            $systemStocks = $_POST['system_stock'] ?? [];
            $comments = $_POST['variance_comment'] ?? [];
            $pdo->beginTransaction();
            $pdo->prepare('DELETE FROM report_stock_status WHERE report_id = ?')->execute([$reportId]);
            $stmt = $pdo->prepare("INSERT INTO report_stock_status (report_id, product_name, stock_level, system_stock, variance, variance_comment)
                VALUES (:report_id, :product_name, :stock_level, :system_stock, :variance, :variance_comment)");
            foreach ($products as $i => $productName) {
                $productName = trim($productName);
                if ($productName === '') {
                    continue;
                }
                $stockLevel = (int) ($stockLevels[$i] ?? 0);
                $systemStock = (int) ($systemStocks[$i] ?? 0);
                $stmt->execute([
                    ':report_id' => $reportId,
                    ':product_name' => $productName,
                    ':stock_level' => $stockLevel,
                    ':system_stock' => $systemStock,
                    ':variance' => $stockLevel - $systemStock,
                    ':variance_comment' => trim($comments[$i] ?? ''),
                ]);
            }
            upsert_progress($pdo, $reportId, 4);
            $pdo->commit();
            json_response(['ok' => true, 'message' => 'Form 04 saved successfully.', 'report_id' => $reportId]);
            break;

        case 'save_form5':
            $reportId = require_existing_report($pdo, $user);
            $issueTypes = $_POST['issue_type'] ?? [];
            $descriptions = $_POST['issue_description'] ?? [];
            $severities = $_POST['severity'] ?? [];
            $pdo->beginTransaction();
            $pdo->prepare('DELETE FROM report_issues WHERE report_id = ?')->execute([$reportId]);
            $stmt = $pdo->prepare("INSERT INTO report_issues (report_id, issue_type, description, severity)
                VALUES (:report_id, :issue_type, :description, :severity)");
            foreach ($issueTypes as $i => $type) {
                $description = trim($descriptions[$i] ?? '');
                if ($description === '') {
                    continue;
                }
                $stmt->execute([
                    ':report_id' => $reportId,
                    ':issue_type' => selected_or_fail(issue_types(), trim($type), 'Issue Type'),
                    ':description' => $description,
                    ':severity' => selected_or_fail(severity_levels(), trim($severities[$i] ?? 'N/A'), 'Severity'),
                ]);
            }
            upsert_progress($pdo, $reportId, 5);
            $pdo->commit();
            json_response(['ok' => true, 'message' => 'Form 05 saved successfully.', 'report_id' => $reportId]);
            break;

        case 'save_form6':
            $reportId = require_existing_report($pdo, $user);
            $pdo->beginTransaction();
            $pdo->prepare('DELETE FROM report_actions_db WHERE report_id = ?')->execute([$reportId]);
            $pdo->prepare('DELETE FROM report_actions_staff WHERE report_id = ?')->execute([$reportId]);

            $stmtDb = $pdo->prepare("INSERT INTO report_actions_db (report_id, action_name, comments) VALUES (:report_id, :action_name, :comments)");
            foreach (($_POST['db_action_name'] ?? []) as $i => $actionName) {
                $actionName = trim($actionName);
                if ($actionName === '') {
                    continue;
                }
                $stmtDb->execute([
                    ':report_id' => $reportId,
                    ':action_name' => $actionName,
                    ':comments' => trim($_POST['db_action_comment'][$i] ?? ''),
                ]);
            }
            $stmtStaff = $pdo->prepare("INSERT INTO report_actions_staff (report_id, staff_role, comments) VALUES (:report_id, :staff_role, :comments)");
            foreach (($_POST['staff_role'] ?? []) as $i => $staffRole) {
                $staffRole = trim($staffRole);
                if ($staffRole === '') {
                    continue;
                }
                $stmtStaff->execute([
                    ':report_id' => $reportId,
                    ':staff_role' => selected_or_fail(['ASM', 'ASE', 'CSR'], $staffRole, 'Staff Role'),
                    ':comments' => trim($_POST['staff_comment'][$i] ?? ''),
                ]);
            }
            upsert_progress($pdo, $reportId, 6);
            $pdo->commit();
            json_response(['ok' => true, 'message' => 'Form 06 saved successfully.', 'report_id' => $reportId]);
            break;

        case 'save_form7':
            $reportId = require_existing_report($pdo, $user);
            $actions = $_POST['follow_action'] ?? [];
            $responsibles = $_POST['follow_responsible'] ?? [];
            $deadlines = $_POST['follow_deadline'] ?? [];
            $pdo->beginTransaction();
            $pdo->prepare('DELETE FROM report_follow_ups WHERE report_id = ?')->execute([$reportId]);
            $stmt = $pdo->prepare("INSERT INTO report_follow_ups (report_id, action_name, responsible_person, deadline_period)
                VALUES (:report_id, :action_name, :responsible_person, :deadline_period)");
            foreach ($actions as $i => $actionName) {
                $actionName = trim($actionName);
                if ($actionName === '') {
                    continue;
                }
                $stmt->execute([
                    ':report_id' => $reportId,
                    ':action_name' => $actionName,
                    ':responsible_person' => trim($responsibles[$i] ?? ''),
                    ':deadline_period' => selected_or_fail(follow_up_periods(), trim($deadlines[$i] ?? '1 month'), 'Deadline'),
                ]);
            }
            upsert_progress($pdo, $reportId, 7);
            $pdo->commit();
            json_response(['ok' => true, 'message' => 'Form 07 saved successfully.', 'report_id' => $reportId]);
            break;

        case 'save_form8':
            $reportId = require_existing_report($pdo, $user);
            $missingForms = missing_required_forms($pdo, $reportId, [1, 2, 3, 4, 5, 6, 7]);
            if ($missingForms) {
                $labels = array_map(static fn (int $no): string => sprintf('Form %02d', $no), $missingForms);
                json_response(['ok' => false, 'message' => 'Please save ' . implode(', ', $labels) . ' before final submission.'], 422);
            }

            $pdo->beginTransaction();
            $stmt = $pdo->prepare('SELECT * FROM report_general_remarks WHERE report_id = ?');
            $stmt->execute([$reportId]);
            $existing = $stmt->fetch() ?: [];

            $removePrepared = ($_POST['prepared_signature_remove'] ?? '0') === '1';
            $removeDistributor = ($_POST['distributor_signature_remove'] ?? '0') === '1';
            $removeEmployee = ($_POST['employee_signature_remove'] ?? '0') === '1';

            $preparedSignature = $removePrepared ? null : (save_base64_image($_POST['prepared_signature_data'] ?? '', 'sig_prepared') ?: ($existing['prepared_by_signature'] ?? null));
            $distributorSignature = $removeDistributor ? null : (save_base64_image($_POST['distributor_signature_data'] ?? '', 'sig_distributor') ?: ($existing['distributor_signature'] ?? null));
            $employeeSignature = $removeEmployee ? null : (save_base64_image($_POST['employee_signature_data'] ?? '', 'sig_employee') ?: ($existing['employee_signature'] ?? null));

            $stmt = $pdo->prepare("INSERT INTO report_general_remarks (
                report_id, remark, prepared_by_signature, distributor_signature, employee_signature, updated_at
            ) VALUES (
                :report_id, :remark, :prepared_by_signature, :distributor_signature, :employee_signature, NOW()
            ) ON DUPLICATE KEY UPDATE
                remark = VALUES(remark),
                prepared_by_signature = VALUES(prepared_by_signature),
                distributor_signature = VALUES(distributor_signature),
                employee_signature = VALUES(employee_signature),
                updated_at = NOW()");
            $stmt->execute([
                ':report_id' => $reportId,
                ':remark' => trim($_POST['remark'] ?? ''),
                ':prepared_by_signature' => $preparedSignature,
                ':distributor_signature' => $distributorSignature,
                ':employee_signature' => $employeeSignature,
            ]);

            $endLat = ($_POST['end_lat'] ?? '') !== '' ? $_POST['end_lat'] : null;
            $endLng = ($_POST['end_lng'] ?? '') !== '' ? $_POST['end_lng'] : null;
            $stmt = $pdo->prepare("UPDATE visit_reports
                SET ended_at = COALESCE(ended_at, NOW()),
                    end_lat = COALESCE(:end_lat, end_lat),
                    end_lng = COALESCE(:end_lng, end_lng),
                    status = 'completed',
                    updated_at = NOW()
                WHERE id = :id");
            $stmt->execute([
                ':end_lat' => $endLat,
                ':end_lng' => $endLng,
                ':id' => $reportId,
            ]);
            upsert_progress($pdo, $reportId, 8);
            $pdo->commit();
            json_response(['ok' => true, 'message' => 'Form 08 saved and report finalized.', 'report_id' => $reportId]);
            break;

        default:
            json_response(['ok' => false, 'message' => 'Unknown action.'], 422);
    }
} catch (Throwable $e) {
    if ($pdo->inTransaction()) {
        $pdo->rollBack();
    }
    json_response(['ok' => false, 'message' => $e->getMessage()], 500);
}
