<?php
// MJ Marketplace v2.9.18 - Deal CSV Import helpers.
// Deals are display/enquiry only. No customer-to-seller payment flow is created here.

if (!function_exists('mj_deal_import_ensure_schema')) {
function mj_deal_import_ensure_schema(): void {
    if (!function_exists('q') || !mj_is_installed()) { return; }
    try {
        q("CREATE TABLE IF NOT EXISTS mj_deal_import_logs (
            id BIGINT AUTO_INCREMENT PRIMARY KEY,
            admin_id INT NULL,
            filename VARCHAR(255) NULL,
            total_rows INT NOT NULL DEFAULT 0,
            imported_rows INT NOT NULL DEFAULT 0,
            updated_rows INT NOT NULL DEFAULT 0,
            skipped_rows INT NOT NULL DEFAULT 0,
            failed_rows INT NOT NULL DEFAULT 0,
            default_status VARCHAR(40) NULL,
            duplicate_mode VARCHAR(40) NULL,
            error_json LONGTEXT NULL,
            ip_address VARCHAR(80) NULL,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            INDEX idx_created(created_at),
            INDEX idx_admin_created(admin_id, created_at)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4");
    } catch (Throwable $e) {}
}
}

if (!function_exists('mj_deal_import_headers')) {
function mj_deal_import_headers(): array {
    return ['title','company_name','seller_email','category_name','country','city','original_price','offer_price','currency','start_date','end_date','short_description','description','terms','whatsapp','phone','email','website','status','featured','sponsored','price_note','image_path','seo_title','seo_description'];
}
}

if (!function_exists('mj_deal_import_sample_rows')) {
function mj_deal_import_sample_rows(): array {
    return [
        ['Data Recovery Diagnosis Offer','MJ Data Recovery Singapore','seller@example.com','Data Recovery','Singapore','Singapore','120','80','SGD',date('Y-m-d'),date('Y-m-d', strtotime('+30 days')),'Free checking for hard disk, SSD, NAS and RAID recovery','Professional data recovery diagnosis for hard disk, SSD, NAS, RAID, USB drive and memory card. Contact seller directly for confirmation and final service arrangement.','Appointment required. Final payment is handled directly between customer and seller. MJ Marketplace does not collect customer payment for this deal.','+6561234567','+6561234567','info@example.com','https://example.com','draft','N','N','From SGD 80','','Data Recovery Diagnosis Deal Singapore','Affordable data recovery diagnosis deal in Singapore.'],
        ['Weekend Beauty Trial Package','Sample Beauty Clinic','beauty@example.com','Services','Singapore','Singapore','188','99','SGD',date('Y-m-d'),date('Y-m-d', strtotime('+14 days')),'Limited-time beauty consultation package','Introductory beauty consultation and trial service package. Customer should contact seller to confirm availability before visiting.','Subject to availability. Appointment required. Payment is direct to seller only.','+6588888888','+6588888888','beauty@example.com','https://example.com','draft','Y','N','Limited slots','','Beauty Trial Package Singapore','Weekend beauty trial package offer in Singapore.'],
        ['Laptop Repair Inspection Deal','Sample IT Services','it@example.com','Electronics','Singapore','Singapore','60','35','SGD',date('Y-m-d'),date('Y-m-d', strtotime('+45 days')),'Laptop inspection and repair quotation','Laptop inspection, diagnosis and repair quotation service. Seller will contact customer after enquiry.','Inspection only. Parts and repair cost quoted separately. No online customer payment through MJ Marketplace.','+6599999999','+6599999999','it@example.com','https://example.com','pending','N','Y','Diagnosis fee from SGD 35','','Laptop Repair Inspection Deal','Laptop repair inspection and diagnosis deal.'],
    ];
}
}

if (!function_exists('mj_deal_import_output_sample_csv')) {
function mj_deal_import_output_sample_csv(): void {
    $filename = 'sample-deal-import.csv';
    header('Content-Type: text/csv; charset=utf-8');
    header('Content-Disposition: attachment; filename="'.$filename.'"');
    echo "\xEF\xBB\xBF";
    $out = fopen('php://output', 'w');
    fputcsv($out, mj_deal_import_headers());
    foreach (mj_deal_import_sample_rows() as $row) { fputcsv($out, $row); }
    fclose($out);
    exit;
}
}

if (!function_exists('mj_deal_import_normalize_key')) {
function mj_deal_import_normalize_key(string $key): string {
    $key = strtolower(trim(preg_replace('/^\xEF\xBB\xBF/', '', $key)));
    $key = preg_replace('/[^a-z0-9]+/', '_', $key);
    return trim((string)$key, '_');
}
}

if (!function_exists('mj_deal_import_read_csv_assoc')) {
function mj_deal_import_read_csv_assoc(string $file, int $maxRows = 2000): array {
    if (!is_file($file)) { throw new RuntimeException('CSV file not found.'); }
    $handle = fopen($file, 'r');
    if (!$handle) { throw new RuntimeException('Unable to read CSV file.'); }
    $headers = fgetcsv($handle);
    if (!$headers) { fclose($handle); throw new RuntimeException('CSV header row is missing.'); }
    $keys = [];
    foreach ($headers as $h) { $keys[] = mj_deal_import_normalize_key((string)$h); }
    $rows = [];
    $line = 1;
    while (($data = fgetcsv($handle)) !== false) {
        $line++;
        if ($line > ($maxRows + 1)) { fclose($handle); throw new RuntimeException('CSV row limit is '.$maxRows.' rows per import. Please split larger files.'); }
        $empty = true;
        foreach ($data as $v) { if (trim((string)$v) !== '') { $empty = false; break; } }
        if ($empty) { continue; }
        $row = ['__line' => $line];
        foreach ($keys as $i => $k) { if ($k !== '') { $row[$k] = trim((string)($data[$i] ?? '')); } }
        $rows[] = $row;
    }
    fclose($handle);
    return $rows;
}
}

if (!function_exists('mj_deal_import_yes')) {
function mj_deal_import_yes($value): int {
    $v = strtolower(trim((string)$value));
    return in_array($v, ['1','y','yes','true','on','featured','sponsored'], true) ? 1 : 0;
}
}

if (!function_exists('mj_deal_import_parse_money')) {
function mj_deal_import_parse_money($value): float {
    $v = preg_replace('/[^0-9\.\-]/', '', (string)$value);
    if ($v === '' || $v === '-' || $v === '.') { return 0.0; }
    return round((float)$v, 2);
}
}

if (!function_exists('mj_deal_import_parse_date')) {
function mj_deal_import_parse_date($value, bool $endOfDay=false): ?string {
    $v = trim((string)$value);
    if ($v === '') { return null; }
    $ts = strtotime($v);
    if (!$ts) { return null; }
    if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $v)) {
        return date('Y-m-d '.($endOfDay ? '23:59:59' : '00:00:00'), $ts);
    }
    return date('Y-m-d H:i:s', $ts);
}
}

if (!function_exists('mj_deal_import_find_by_name')) {
function mj_deal_import_find_by_name(string $table, string $name, string $where = '1=1'): ?array {
    $table = preg_replace('/[^a-zA-Z0-9_]/', '', $table);
    if ($table === '' || !table_exists($table)) { return null; }
    $name = trim($name);
    if ($name === '') { return null; }
    try {
        return one("SELECT * FROM `{$table}` WHERE {$where} AND (LOWER(name)=LOWER(?) OR LOWER(slug)=LOWER(?)) LIMIT 1", [$name, slugify($name)]);
    } catch (Throwable $e) {
        try { return one("SELECT * FROM `{$table}` WHERE {$where} AND LOWER(name)=LOWER(?) LIMIT 1", [$name]); } catch (Throwable $ignore) { return null; }
    }
}
}

if (!function_exists('mj_deal_import_find_user_by_email')) {
function mj_deal_import_find_user_by_email(string $email): ?array {
    if (!table_exists('mj_users')) { return null; }
    $email = trim($email);
    if ($email === '' || !filter_var($email, FILTER_VALIDATE_EMAIL)) { return null; }
    try { return one('SELECT * FROM mj_users WHERE LOWER(email)=LOWER(?) LIMIT 1', [$email]); } catch (Throwable $e) { return null; }
}
}

if (!function_exists('mj_deal_import_duplicate_id')) {
function mj_deal_import_duplicate_id(array $data): int {
    if (!table_exists('mj_deals')) { return 0; }
    try {
        $row = one('SELECT id FROM mj_deals WHERE LOWER(title)=LOWER(?) AND (company_id <=> ?) AND (country_id <=> ?) AND (category_id <=> ?) AND ABS(COALESCE(deal_price,0)-?) < 0.01 LIMIT 1', [
            (string)$data['title'], $data['company_id'], $data['country_id'], $data['category_id'], (float)$data['deal_price']
        ]);
        return (int)($row['id'] ?? 0);
    } catch (Throwable $e) { return 0; }
}
}

if (!function_exists('mj_deal_import_row_to_data')) {
function mj_deal_import_row_to_data(array $row, string $defaultStatus = 'draft'): array {
    mj_deal_ensure_schema();
    $errors = [];
    $warnings = [];
    $line = (int)($row['__line'] ?? 0);

    $title = trim((string)($row['title'] ?? $row['deal_title'] ?? ''));
    if ($title === '') { $errors[] = 'Title is required.'; }
    if ($title !== '' && mb_strlen($title) < 5) { $errors[] = 'Title is too short.'; }

    $countryName = trim((string)($row['country'] ?? $row['country_name'] ?? ''));
    $country = $countryName !== '' ? mj_deal_import_find_by_name('mj_countries', $countryName, 'is_active=1') : null;
    if (!$country) { $errors[] = 'Country not found or inactive: '.($countryName ?: '(empty)'); }

    $categoryName = trim((string)($row['category_name'] ?? $row['category'] ?? ''));
    $category = $categoryName !== '' ? mj_deal_import_find_by_name('mj_categories', $categoryName, "is_active=1 AND type IN ('marketplace','service','company')") : null;
    if ($categoryName !== '' && !$category) { $warnings[] = 'Category not found: '.$categoryName.'. Deal will import without category.'; }
    if ($categoryName === '') { $warnings[] = 'Category is empty. Deal will import without category.'; }

    $cityName = trim((string)($row['city'] ?? $row['city_name'] ?? ''));
    $city = null;
    if ($cityName !== '' && $country) {
        try { $city = one('SELECT * FROM mj_cities WHERE country_id=? AND is_active=1 AND (LOWER(name)=LOWER(?) OR LOWER(slug)=LOWER(?)) LIMIT 1', [(int)$country['id'], $cityName, slugify($cityName)]); } catch (Throwable $e) { $city = null; }
        if (!$city) { $warnings[] = 'City not found: '.$cityName.'. Deal will import without city.'; }
    }

    $companyName = trim((string)($row['company_name'] ?? $row['merchant'] ?? $row['company'] ?? ''));
    $company = $companyName !== '' ? mj_deal_import_find_by_name('mj_companies', $companyName) : null;
    if ($companyName !== '' && !$company) { $warnings[] = 'Company not found: '.$companyName.'. Deal will import as direct seller/no company.'; }

    $sellerEmail = trim((string)($row['seller_email'] ?? $row['user_email'] ?? ''));
    $user = $sellerEmail !== '' ? mj_deal_import_find_user_by_email($sellerEmail) : null;
    if ($sellerEmail !== '' && !$user) { $warnings[] = 'Seller email not found: '.$sellerEmail.'. Deal will not be linked to user.'; }
    if (!$user && $company && !empty($company['user_id'])) { $user = ['id' => (int)$company['user_id']]; }

    $original = mj_deal_import_parse_money($row['original_price'] ?? $row['normal_price'] ?? $row['price'] ?? 0);
    $offer = mj_deal_import_parse_money($row['offer_price'] ?? $row['deal_price'] ?? $row['discount_price'] ?? 0);
    if ($original < 0 || $offer < 0) { $errors[] = 'Price cannot be negative.'; }
    if ($original > 0 && $offer > $original) { $errors[] = 'Offer price cannot be higher than original price.'; }

    $email = trim((string)($row['email'] ?? $row['contact_email'] ?? ''));
    if ($email !== '' && !filter_var($email, FILTER_VALIDATE_EMAIL)) { $errors[] = 'Contact email is invalid.'; }
    $currency = strtoupper(substr(preg_replace('/[^A-Z]/i', '', (string)($row['currency'] ?? $row['currency_code'] ?? ($country['currency_code'] ?? 'SGD'))), 0, 8));
    if ($currency === '') { $currency = 'SGD'; }

    $startAt = mj_deal_import_parse_date($row['start_date'] ?? $row['start_at'] ?? '', false);
    $endAt = mj_deal_import_parse_date($row['end_date'] ?? $row['end_at'] ?? '', true);
    if (trim((string)($row['start_date'] ?? $row['start_at'] ?? '')) !== '' && !$startAt) { $errors[] = 'Start date is invalid.'; }
    if (trim((string)($row['end_date'] ?? $row['end_at'] ?? '')) !== '' && !$endAt) { $errors[] = 'End date is invalid.'; }
    if ($startAt && $endAt && strtotime($endAt) < strtotime($startAt)) { $errors[] = 'End date must be after start date.'; }

    $rowStatus = strtolower(trim((string)($row['status'] ?? '')));
    $allowedStatus = ['draft','pending','active','paused','expired','rejected','hidden'];
    $defaultStatus = strtolower(trim($defaultStatus));
    if ($defaultStatus === 'use_file') {
        $status = $rowStatus !== '' ? $rowStatus : 'draft';
    } else {
        $status = in_array($defaultStatus, ['draft','pending','active'], true) ? $defaultStatus : 'draft';
    }
    if (!in_array($status, $allowedStatus, true)) { $warnings[] = 'Invalid status changed to draft.'; $status = 'draft'; }

    $description = trim((string)($row['description'] ?? $row['full_description'] ?? ''));
    $short = trim((string)($row['short_description'] ?? $row['summary'] ?? ''));
    $terms = trim((string)($row['terms'] ?? $row['terms_and_conditions'] ?? ''));
    if ($terms === '') { $terms = 'Customer contacts seller directly. MJ Marketplace does not collect customer payment for this deal.'; }

    $data = [
        'user_id' => $user ? (int)$user['id'] : null,
        'company_id' => $company ? (int)$company['id'] : null,
        'category_id' => $category ? (int)$category['id'] : null,
        'country_id' => $country ? (int)$country['id'] : null,
        'city_id' => $city ? (int)$city['id'] : null,
        'deal_type' => trim((string)($row['deal_type'] ?? 'normal')) ?: 'normal',
        'title' => $title,
        'slug' => '',
        'short_description' => $short,
        'description' => $description,
        'image_path' => trim((string)($row['image_path'] ?? $row['image'] ?? '')),
        'original_price' => $original,
        'deal_price' => $offer,
        'discount_percent' => mj_deal_discount_percent($original, $offer),
        'price_note' => trim((string)($row['price_note'] ?? '')),
        'currency_code' => $currency,
        'start_at' => $startAt,
        'end_at' => $endAt,
        'status' => $status,
        'is_featured' => mj_deal_import_yes($row['featured'] ?? $row['is_featured'] ?? '0'),
        'is_sponsored' => mj_deal_import_yes($row['sponsored'] ?? $row['is_sponsored'] ?? '0'),
        'contact_phone' => trim((string)($row['phone'] ?? $row['contact_phone'] ?? '')),
        'contact_whatsapp' => trim((string)($row['whatsapp'] ?? $row['contact_whatsapp'] ?? '')),
        'contact_email' => $email,
        'terms' => $terms,
        'admin_note' => 'Imported by deal CSV. '.trim((string)($row['website'] ?? '')),
    ];
    $data['quality_score'] = mj_deal_quality_score($data);
    $duplicateId = $title !== '' ? mj_deal_import_duplicate_id($data) : 0;
    if ($duplicateId > 0) { $warnings[] = 'Possible duplicate of deal #'.$duplicateId.'.'; }

    return ['line'=>$line,'data'=>$data,'errors'=>$errors,'warnings'=>$warnings,'duplicate_id'=>$duplicateId,'raw'=>$row];
}
}

if (!function_exists('mj_deal_import_preview_rows')) {
function mj_deal_import_preview_rows(array $rows, string $defaultStatus = 'draft'): array {
    $preview = [];
    foreach ($rows as $row) { $preview[] = mj_deal_import_row_to_data($row, $defaultStatus); }
    return $preview;
}
}

if (!function_exists('mj_deal_import_insert_or_update')) {
function mj_deal_import_insert_or_update(array $previewRow, string $duplicateMode = 'skip'): array {
    $errors = $previewRow['errors'] ?? [];
    if ($errors) { return ['status'=>'failed','message'=>implode(' ', $errors), 'id'=>0]; }
    $data = $previewRow['data'] ?? [];
    $duplicateId = (int)($previewRow['duplicate_id'] ?? 0);
    $duplicateMode = in_array($duplicateMode, ['skip','draft_anyway','update_draft'], true) ? $duplicateMode : 'skip';
    if ($duplicateId > 0 && $duplicateMode === 'skip') { return ['status'=>'skipped','message'=>'Skipped duplicate deal #'.$duplicateId, 'id'=>$duplicateId]; }
    if ($duplicateId > 0 && $duplicateMode === 'update_draft') {
        $existing = one('SELECT * FROM mj_deals WHERE id=? LIMIT 1', [$duplicateId]);
        if ($existing && strtolower((string)$existing['status']) === 'draft') {
            $data['slug'] = $existing['slug'] ?: mj_slug_unique('mj_deals', (string)$data['title'], $duplicateId);
            $data = mj_deal_filter_existing_columns($data);
            $sets=[]; $params=[];
            foreach ($data as $k=>$v) { if ($k === 'id') { continue; } $sets[]='`'.$k.'`=?'; $params[]=$v; }
            $sets[]='updated_at=NOW()'; $params[]=$duplicateId;
            q('UPDATE mj_deals SET '.implode(',', $sets).' WHERE id=?', $params);
            return ['status'=>'updated','message'=>'Updated draft duplicate #'.$duplicateId, 'id'=>$duplicateId];
        }
        return ['status'=>'skipped','message'=>'Duplicate exists but is not draft: #'.$duplicateId, 'id'=>$duplicateId];
    }
    if ($duplicateId > 0 && $duplicateMode === 'draft_anyway') { $data['status'] = 'draft'; }
    $data['slug'] = mj_slug_unique('mj_deals', (string)$data['title']);
    $data = mj_deal_filter_existing_columns($data);
    $cols = array_keys($data);
    $ph = array_fill(0, count($cols), '?');
    q('INSERT INTO mj_deals(`'.implode('`,`', $cols).'`,created_at,updated_at) VALUES('.implode(',', $ph).',NOW(),NOW())', array_values($data));
    return ['status'=>'imported','message'=>'Imported', 'id'=>(int)db()->lastInsertId()];
}
}

if (!function_exists('mj_deal_import_store_log')) {
function mj_deal_import_store_log(string $filename, int $total, int $imported, int $updated, int $skipped, int $failed, string $status, string $duplicateMode, array $errors = []): void {
    mj_deal_import_ensure_schema();
    try {
        q('INSERT INTO mj_deal_import_logs(admin_id,filename,total_rows,imported_rows,updated_rows,skipped_rows,failed_rows,default_status,duplicate_mode,error_json,ip_address,created_at) VALUES(?,?,?,?,?,?,?,?,?,?,?,NOW())', [
            (int)($_SESSION['admin_id'] ?? 0), $filename, $total, $imported, $updated, $skipped, $failed, $status, $duplicateMode, json_encode(array_slice($errors,0,200)), $_SERVER['REMOTE_ADDR'] ?? ''
        ]);
    } catch (Throwable $e) {}
}
}
