<?php
/**
 * File: api/karigar/issue_add.php
 * Purpose: Karigar কে গোল্ড issue (full transaction)
 * Method : POST
 * Input  : {
 *   karigar_party_id, issue_date, source_type, source_reference_id,
 *   karat, purity_percent, gross_weight_gram, pieces,
 *   item_description, location_id, job_id (optional), note
 * }
 * Side-effects:
 *   1) karigar_issues INSERT
 *   2) karigar_ledger INSERT (ISSUE_GOLD)
 *   3) gold_ledger INSERT (entry_type='ADJUSTMENT', party_id=karigar)
 *   4) old_gold_movements INSERT (যদি OLD_GOLD_STOCK)
 *   5) old_gold_stock.available_* decrement (যদি OLD_GOLD_STOCK)
 *   6) karigar_jobs summary UPDATE (যদি job_id)
 *   7) audit_log
 * Date: 2026-05-27
 */

ini_set('display_errors', 0);
error_reporting(E_ALL);

header('Content-Type: application/json; charset=utf-8');

require_once __DIR__ . '/../../config/session.php';
require_once __DIR__ . '/../../config/db.php';

function out_json($code, $success, $message, $data = null) {
    http_response_code($code);
    echo json_encode([
        'success' => (bool)$success,
        'status'  => (bool)$success,
        'message' => $message,
        'data'    => $data
    ], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
    exit;
}

if (function_exists('is_logged_in') && !is_logged_in()) {
    out_json(401, false, 'লগইন প্রয়োজন', null);
}

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    out_json(405, false, 'শুধু POST অনুরোধ গ্রহণযোগ্য', null);
}

if (!isset($pdo) || !($pdo instanceof PDO)) {
    out_json(500, false, 'Database connection পাওয়া যায়নি', null);
}

$raw  = file_get_contents('php://input');
$data = json_decode($raw, true);
if (!is_array($data)) $data = $_POST;

// ===== Inputs =====
$karigar_party_id    = (int)($data['karigar_party_id'] ?? 0);
$issue_date          = trim((string)($data['issue_date'] ?? date('Y-m-d')));
$source_type         = trim((string)($data['source_type'] ?? 'GOLD_STOCK'));
$source_reference_id = isset($data['source_reference_id']) && $data['source_reference_id'] !== ''
                         ? (int)$data['source_reference_id'] : null;
$karat               = trim((string)($data['karat'] ?? '22K'));
$purity_percent      = (float)($data['purity_percent'] ?? 0);
$gross_weight_gram   = (float)($data['gross_weight_gram'] ?? 0);
$pieces              = (int)($data['pieces'] ?? 0);
$item_description    = trim((string)($data['item_description'] ?? ''));
$location_id         = (int)($data['location_id'] ?? 1);
$job_id              = isset($data['job_id']) && $data['job_id'] !== '' ? (int)$data['job_id'] : null;
$note                = trim((string)($data['note'] ?? ''));

// ===== Validate =====
if ($karigar_party_id <= 0) out_json(400, false, 'Karigar select করুন', null);
if ($gross_weight_gram <= 0) out_json(400, false, 'Gross weight ০-এর বেশি হতে হবে', null);
if ($purity_percent <= 0 || $purity_percent > 100) out_json(400, false, 'Purity ১-১০০ এর মধ্যে দিন', null);

$allowed_karat = ['24K','22K','21K','18K','other'];
if (!in_array($karat, $allowed_karat, true)) {
    out_json(400, false, 'Invalid karat', null);
}

$allowed_source = ['GOLD_STOCK','OLD_GOLD_STOCK','OTHER'];
if (!in_array($source_type, $allowed_source, true)) {
    out_json(400, false, 'Invalid source type', null);
}

if ($source_type === 'OLD_GOLD_STOCK' && $source_reference_id === null) {
    out_json(400, false, 'OLD_GOLD_STOCK select করলে কোন lot সেটা দিন', null);
}

// Auto pure weight
$pure_weight_gram = round($gross_weight_gram * ($purity_percent / 100.0), 4);

try {
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

    // ===== Karigar exists check =====
    $chk = $pdo->prepare("SELECT id, name, is_karigar, deleted_at
                          FROM parties WHERE id = ? LIMIT 1");
    $chk->execute([$karigar_party_id]);
    $karigar = $chk->fetch(PDO::FETCH_ASSOC);

    if (!$karigar)                                  out_json(404, false, 'এই karigar পাওয়া যায়নি', null);
    if ((int)$karigar['is_karigar'] !== 1)          out_json(400, false, 'এই party karigar না', null);
    if ($karigar['deleted_at'] !== null)            out_json(400, false, 'এই karigar deleted', null);

    // ===== Old gold stock check (যদি OLD_GOLD_STOCK) =====
    if ($source_type === 'OLD_GOLD_STOCK') {
        $ogChk = $pdo->prepare("SELECT id, available_weight_gram, available_pure_gram, status
                                FROM old_gold_stock
                                WHERE id = ? AND deleted_at IS NULL LIMIT 1");
        $ogChk->execute([$source_reference_id]);
        $og = $ogChk->fetch(PDO::FETCH_ASSOC);

        if (!$og) {
            out_json(404, false, 'Old gold lot পাওয়া যায়নি', null);
        }
        if ((float)$og['available_weight_gram'] < $gross_weight_gram - 0.0001) {
            out_json(400, false,
                'Old gold lot এ পর্যাপ্ত weight নেই (available: '
                . round($og['available_weight_gram'], 4) . 'g, requested: '
                . $gross_weight_gram . 'g)', null);
        }
    }

    // ===== Job check (যদি দেওয়া হয়) =====
    if ($job_id !== null) {
        $jobChk = $pdo->prepare("SELECT id, karigar_party_id, status, deleted_at
                                 FROM karigar_jobs WHERE id = ? LIMIT 1");
        $jobChk->execute([$job_id]);
        $job = $jobChk->fetch(PDO::FETCH_ASSOC);

        if (!$job)                                          out_json(404, false, 'Job পাওয়া যায়নি', null);
        if ($job['deleted_at'] !== null)                    out_json(400, false, 'Job deleted', null);
        if ((int)$job['karigar_party_id'] !== $karigar_party_id) {
            out_json(400, false, 'Job অন্য karigar এর', null);
        }
        if (in_array($job['status'], ['SETTLED','CANCELLED'], true)) {
            out_json(400, false, 'Job ' . $job['status'] . ' — issue করা যাবে না', null);
        }
    }

    // ===== Begin transaction =====
    $pdo->beginTransaction();

    $user_id = (int)($_SESSION['user_id'] ?? 0);
    $ip      = $_SERVER['REMOTE_ADDR'] ?? '';

    // 1) karigar_issues INSERT
    $ins = $pdo->prepare("
        INSERT INTO karigar_issues
            (issue_date, karigar_party_id, job_id, source_type, source_reference_id,
             karat, purity_percent, gross_weight_gram, pure_weight_gram, pieces,
             item_description, location_id, note, created_by, created_at)
        VALUES
            (:issue_date, :karigar_id, :job_id, :source_type, :source_ref,
             :karat, :purity, :gross, :pure, :pieces,
             :item_desc, :location, :note, :created_by, NOW())
    ");
    $ins->execute([
        ':issue_date'  => $issue_date,
        ':karigar_id'  => $karigar_party_id,
        ':job_id'      => $job_id,
        ':source_type' => $source_type,
        ':source_ref'  => $source_reference_id,
        ':karat'       => $karat,
        ':purity'      => $purity_percent,
        ':gross'       => $gross_weight_gram,
        ':pure'        => $pure_weight_gram,
        ':pieces'      => $pieces,
        ':item_desc'   => $item_description,
        ':location'    => $location_id,
        ':note'        => $note,
        ':created_by'  => $user_id
    ]);
    $issue_id = (int)$pdo->lastInsertId();

    // 2) karigar_ledger INSERT
    $led = $pdo->prepare("
        INSERT INTO karigar_ledger
            (entry_date, karigar_party_id, entry_type, reference_table, reference_id,
             gold_in_pure_gram, gold_out_pure_gram, cash_in, cash_out,
             note, created_by, created_at)
        VALUES
            (:entry_date, :karigar_id, 'ISSUE_GOLD', 'karigar_issues', :ref_id,
             0, :pure_out, 0, 0,
             :note, :created_by, NOW())
    ");
    $led->execute([
        ':entry_date' => $issue_date,
        ':karigar_id' => $karigar_party_id,
        ':ref_id'     => $issue_id,
        ':pure_out'   => $pure_weight_gram,
        ':note'       => 'Issue #' . $issue_id . ' — ' . $item_description,
        ':created_by' => $user_id
    ]);

    // 3) gold_ledger INSERT (overall stock movement tracking)
    $glIns = $pdo->prepare("
        INSERT INTO gold_ledger
            (entry_date, party_id, location_id, entry_type, reference_id,
             gold_in, gold_out, amount_in, amount_out, karat, note, created_by, created_at)
        VALUES
            (:entry_date, :party_id, :location_id, 'ADJUSTMENT', :ref_id,
             0, :gross_out, 0, 0, :karat, :note, :created_by, NOW())
    ");
    $glIns->execute([
        ':entry_date'  => $issue_date,
        ':party_id'    => $karigar_party_id,
        ':location_id' => $location_id,
        ':ref_id'      => $issue_id,
        ':gross_out'   => $gross_weight_gram,
        ':karat'       => $karat,
        ':note'        => 'Karigar Issue #' . $issue_id . ' (' . $karigar['name'] . ')',
        ':created_by'  => $user_id
    ]);

    // 4 + 5) OLD_GOLD_STOCK source হলে — movement + available decrement
    if ($source_type === 'OLD_GOLD_STOCK') {
        $ogm = $pdo->prepare("
            INSERT INTO old_gold_movements
                (movement_date, old_gold_stock_id, movement_type,
                 gross_weight_gram, pure_weight_gram,
                 to_party_id, to_location_id, reference_table, reference_id,
                 note, created_by, created_at)
            VALUES
                (:mdate, :stock_id, 'OUT_ISSUE_TO_KARIGAR',
                 :gross, :pure,
                 :to_party, :to_loc, 'karigar_issues', :ref_id,
                 :note, :created_by, NOW())
        ");
        $ogm->execute([
            ':mdate'      => $issue_date,
            ':stock_id'   => $source_reference_id,
            ':gross'      => $gross_weight_gram,
            ':pure'       => $pure_weight_gram,
            ':to_party'   => $karigar_party_id,
            ':to_loc'     => $location_id,
            ':ref_id'     => $issue_id,
            ':note'       => 'Issued to karigar: ' . $karigar['name'],
            ':created_by' => $user_id
        ]);

        // Decrement old_gold_stock
        $ogUpd = $pdo->prepare("
            UPDATE old_gold_stock
            SET available_weight_gram = GREATEST(0, available_weight_gram - :gross),
                available_pure_gram   = GREATEST(0, available_pure_gram - :pure),
                status = CASE
                    WHEN (available_weight_gram - :gross2) <= 0.0001 THEN 'issued'
                    WHEN (available_weight_gram - :gross3) < gross_weight_gram THEN 'partial'
                    ELSE status
                END
            WHERE id = :id
        ");
        $ogUpd->execute([
            ':gross'  => $gross_weight_gram,
            ':pure'   => $pure_weight_gram,
            ':gross2' => $gross_weight_gram,
            ':gross3' => $gross_weight_gram,
            ':id'     => $source_reference_id
        ]);
    }

    // 6) Job summary update (যদি job_id)
    if ($job_id !== null) {
        $jobUpd = $pdo->prepare("
            UPDATE karigar_jobs
            SET total_issued_gross = COALESCE(total_issued_gross, 0) + :gross,
                total_issued_pure  = COALESCE(total_issued_pure, 0)  + :pure,
                status = CASE WHEN status = 'OPEN' THEN 'IN_PROGRESS' ELSE status END
            WHERE id = :id
        ");
        $jobUpd->execute([
            ':gross' => $gross_weight_gram,
            ':pure'  => $pure_weight_gram,
            ':id'    => $job_id
        ]);
    }

    // 7) Audit log
    try {
        $alog = $pdo->prepare("
            INSERT INTO audit_log
                (table_name, record_id, action, changed_by, changed_at, ip_address, new_values, note)
            VALUES
                ('karigar_issues', ?, 'INSERT', ?, NOW(), ?, ?, ?)
        ");
        $alog->execute([
            $issue_id,
            $user_id,
            $ip,
            json_encode([
                'karigar_party_id' => $karigar_party_id,
                'karigar_name'     => $karigar['name'],
                'gross'            => $gross_weight_gram,
                'pure'             => $pure_weight_gram,
                'karat'            => $karat,
                'source'           => $source_type,
                'job_id'           => $job_id
            ], JSON_UNESCAPED_UNICODE),
            'Karigar issue #' . $issue_id
        ]);
    } catch (Throwable $e) { /* silent */ }

    $pdo->commit();

    out_json(200, true, 'Issue successfully recorded ✅', [
        'issue_id'         => $issue_id,
        'karigar_name'     => $karigar['name'],
        'gross_weight'     => $gross_weight_gram,
        'pure_weight'      => $pure_weight_gram,
        'karat'            => $karat,
        'source_type'      => $source_type,
        'job_id'           => $job_id
    ]);

} catch (Throwable $e) {
    if ($pdo->inTransaction()) $pdo->rollBack();
    out_json(500, false, 'সার্ভার ত্রুটি: ' . $e->getMessage(), null);
}
