// app.js
// Main application logic for branch management system

const API_KEY_DEFAULT = 'service.d3c8ad2c2dda4d7bb64811075c939f84';
const NESHAN_MAP_KEY  = 'web.cd2e15ba00974242b67e731f0fe4bae4';

// Status definitions with labels and colors
const STATUSES = [
    { key: 'location_sent',      label: 'ارسال لوکیشن',      color: '#6b7280' },
    { key: 'area_manager_visit', label: 'بازدید مدیر منطقه', color: '#f59e0b' },
    { key: 'exec_manager_visit', label: 'بازدید مدیر اجرایی', color: '#8b5cf6' },
    { key: 'contract',           label: 'قرارداد',           color: '#3b82f6' },
    { key: 'contract_sent',      label: 'ارسال قرارداد',     color: '#10b981' },
    { key: 'hq_receive',         label: 'دریافت ستاد',       color: '#059669' },
];

// SLA days configuration for each status
const STAGE_SLA_DAYS = {
    location_sent:      0,
    area_manager_visit: 3,
    exec_manager_visit: 2,
    contract:           2,
    contract_sent:      1,
    hq_receive:         2,
};

// CSV export fields order
const CSV_FIELDS = [
    'status', 'store_code', 'store_name', 'lat', 'lng',
    'formatted_address', 'city', 'state', 'municipality_zone',
    'in_traffic_zone', 'in_odd_even_zone', 'village', 'county',
    'district', 'is_franchise',
];

// Application state
let stores = [];
let editingIndex = -1;
let modalMap = null;
let modalMarker = null;
let overviewMap = null;
let overviewMarkers = [];
let activeStatusFilter = 'ALL';
let geoFetched = false;
let needsAddressFetch = false;

// Initialize application on DOM ready
document.addEventListener('DOMContentLoaded', async () => {
    await loadFromStorage();
    renderDashboard();
    renderTable();
    updateCount();
    setupNavigation();
    setupSearch();
    setupKeyboardShortcuts();
    populateStatusSelect();
    buildStatusFilterTabs();
    
    const unlockBtn = document.getElementById('unlock-map-btn');
    if(unlockBtn) {
        unlockBtn.addEventListener('click', () => {
            document.getElementById('map-lock-overlay').classList.add('hidden');
            if(modalMap) modalMap.invalidateSize();
        });
    }
});

// Utility functions
const esc = (val) => {
    const div = document.createElement('div');
    div.textContent = String(val ?? '');
    return div.innerHTML;
};

const generateId = () =>
    Date.now().toString(36) + '-' + Math.random().toString(36).substr(2, 9);

const nowISO = () => new Date().toISOString();

const daysBetween = (isoDate) => {
    if (!isoDate) return 0;
    return Math.floor((Date.now() - new Date(isoDate)) / 86_400_000);
};

const getStatusObj = (key) =>
    STATUSES.find(s => s.key === key) ?? STATUSES[0];

const getStatusLabel = (key) => getStatusObj(key).label;
const getStatusColor = (key) => getStatusObj(key).color;

const formatDaysAgo = (isoDate) => {
    if (!isoDate) return '-';
    const d = daysBetween(isoDate);
    if (d === 0) return 'امروز';
    if (d === 1) return 'دیروز';
    return `${d} روز پیش`;
};

const daysInCurrentStage = (store) => {
    const history = store.status_history;
    const ref = history?.length
        ? history[history.length - 1].at
        : store.created_at;
    return daysBetween(ref);
};

// Load data from server (excluding deleted stores)
async function loadFromStorage() {
    try {
        const res = await fetch('api.php?action=load');
        const allData = res.ok ? await res.json() : [];
        stores = allData.filter(store => store.is_deleted !== true);
    } catch (err) {
        console.error('Load error:', err);
        stores = [];
    }
}

// Save single store data to server
async function saveToStorage(singleStoreToSave) {
    if (!singleStoreToSave) return;
    try {
        const res = await fetch('api.php?action=save', {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify(singleStoreToSave),
        });
        const { success } = await res.json();
        if (!success) showToast('خطا در ذخیره اطلاعات روی سرور', 'error');
    } catch (err) {
        console.error('Save error:', err);
        showToast('خطا در ارتباط با سرور هنگام ذخیره‌سازی', 'error');
    }
}

// Navigation system
const VIEW_MAP = {
    dashboard:    'viewDashboard',
    pipeline:     'viewPipeline',
    table:        'viewTable',
    'map-overview': 'viewMapOverview',
    performance:  'viewPerformance',
    issues:       'viewIssues',
    export:       'viewExport',
};

const PAGE_TITLES = {
    dashboard:    'داشبورد',
    pipeline:     'Pipeline',
    table:        'جدول شعب',
    'map-overview': 'نقشه',
    performance:  'تحلیل عملکرد',
    issues:       'مشکلات',
    export:       'خروجی',
};

const VIEW_RENDERERS = {
    dashboard:    renderDashboard,
    pipeline:     renderPipeline,
    table:        renderTable,
    'map-overview': renderOverviewMap,
    performance:  renderPerformance,
    issues:       renderIssues,
    export:       renderExportPreview,
};

function setupNavigation() {
    document.querySelectorAll('.nav-item').forEach(item => {
        item.addEventListener('click', (e) => {
            e.preventDefault();
            const view = item.dataset.view;

            document.querySelectorAll('.nav-item').forEach(n => n.classList.remove('active'));
            item.classList.add('active');

            document.querySelectorAll('.view-section').forEach(v => v.classList.remove('active'));
            document.getElementById(VIEW_MAP[view])?.classList.add('active');

            document.getElementById('pageTitle').textContent = PAGE_TITLES[view] ?? '';

            const showAdd = ['table', 'dashboard', 'pipeline'].includes(view);
            document.getElementById('btnAddNew').style.display = showAdd ? 'inline-flex' : 'none';

            VIEW_RENDERERS[view]?.();
        });
    });
}

// Search and filtering
function setupSearch() {
    document.getElementById('searchInput').addEventListener('input', () => {
        renderTable();
        renderPipeline();
    });
}

const getSearchTerm = () =>
    document.getElementById('searchInput').value.trim().toLowerCase();

const matchesSearch = (store, term) => {
    if (!term) return true;
    return [
        store.store_name, store.store_code, store.city,
        store.state, store.formatted_address, store.county,
        store.district, store.village, getStatusLabel(store.status),
    ].some(f => (f ?? '').toLowerCase().includes(term));
};

const getFilteredStores = () => {
    const term = getSearchTerm();
    return stores.filter(s =>
        (activeStatusFilter === 'ALL' || s.status === activeStatusFilter) &&
        matchesSearch(s, term)
    );
};

function buildStatusFilterTabs() {
    const container = document.getElementById('statusFilterTabs');

    const makeTab = (label, statusKey = null) => {
        const btn = document.createElement('button');
        btn.className = 'status-filter-tab' + (statusKey === null ? ' active' : '');
        btn.textContent = label;
        if (statusKey) btn.dataset.status = statusKey;
        btn.addEventListener('click', () => {
            activeStatusFilter = statusKey ?? 'ALL';
            updateFilterTabUI();
            renderTable();
        });
        return btn;
    };

    container.append(
        makeTab('همه'),
        ...STATUSES.map(s => makeTab(s.label, s.key))
    );
}

function updateFilterTabUI() {
    document.querySelectorAll('.status-filter-tab').forEach(btn => {
        const match = activeStatusFilter === 'ALL'
            ? !btn.dataset.status
            : btn.dataset.status === activeStatusFilter;
        btn.classList.toggle('active', match);
    });
}

// Keyboard shortcuts
function setupKeyboardShortcuts() {
    document.addEventListener('keydown', (e) => {
        if (e.key === 'Escape') {
            closeModal();
            closeDeleteModal();
            closeIssueModal();
        }
        if (e.ctrlKey && e.key === 'n') { e.preventDefault(); openAddModal(); }
        if (e.ctrlKey && e.key === '/') { e.preventDefault(); document.getElementById('searchInput').focus(); }
    });
}

// Toast notifications
function showToast(message, type = 'info') {
    const toast = Object.assign(document.createElement('div'), {
        className: `toast ${type}`,
        textContent: message,
    });
    document.getElementById('toastContainer').appendChild(toast);
    setTimeout(() => {
        Object.assign(toast.style, { opacity: '0', transform: 'translateY(10px)', transition: 'all 0.3s' });
        setTimeout(() => toast.remove(), 300);
    }, 3000);
}

// Dashboard rendering
function renderDashboard() {
    renderKPIs();
    renderPipelineBar();
    renderActivityList();
    renderAlerts();
}

function renderKPIs() {
    const total    = stores.length;
    const active   = stores.filter(s => s.status === 'ACTIVE').length;
    const inDev    = stores.filter(s => s.status === 'DEVELOPMENT').length;
    const rejected = stores.filter(s => s.status === 'REJECTED').length;
    const inPipeline = stores.filter(s => !['ACTIVE', 'REJECTED'].includes(s.status)).length;

    const activatedStores = stores.filter(s => s.status === 'ACTIVE' && s.created_at);
    const avgDays = activatedStores.length
        ? Math.round(activatedStores.reduce((sum, s) => sum + daysBetween(s.created_at), 0) / activatedStores.length)
        : 0;

    const kpis = [
        { label: 'کل شعب',              value: total,                            color: 'var(--accent)',  sub: '' },
        { label: 'فعال',                 value: active,                           color: 'var(--success)', sub: total ? `${Math.round(active / total * 100)}%` : '0%' },
        { label: 'در Pipeline',          value: inPipeline,                       color: 'var(--purple)',  sub: 'در حال پیشرفت' },
        { label: 'در حال توسعه',         value: inDev,                            color: '#3b82f6',        sub: '' },
        { label: 'رد شده',               value: rejected,                         color: '#dc2626',        sub: '' },
        { label: 'میانگین تا فعال‌سازی', value: avgDays ? `${avgDays} روز` : '-', color: 'var(--warning)', sub: `${activatedStores.length} شعبه فعال` },
    ];

    document.getElementById('kpiGrid').innerHTML = kpis.map(k => `
        <div class="kpi-card">
            <div class="kpi-label">${esc(k.label)}</div>
            <div class="kpi-value" style="color:${k.color}">${esc(String(k.value))}</div>
            ${k.sub ? `<div class="kpi-sub">${esc(k.sub)}</div>` : ''}
        </div>
    `).join('');
}

function renderPipelineBar() {
    const container = document.getElementById('pipelineBar');
    if (!stores.length) {
        container.innerHTML = '<div style="padding:16px;color:var(--text-muted);font-size:13px;">هنوز داده‌ای ثبت نشده</div>';
        return;
    }

    const counts = Object.fromEntries(STATUSES.map(s => [s.key, 0]));
    stores.forEach(s => { if (s.status in counts) counts[s.status]++; });
    const total = stores.length;

    container.innerHTML = STATUSES.map(({ key, label, color }) => {
        const count = counts[key];
        if (!count) return '';
        const pct = count / total * 100;
        const text = pct > 5 ? `${label} (${count})` : count;
        return `<div class="pipeline-bar-segment" style="flex:${pct};background:${color};" title="${label}: ${count}">${text}</div>`;
    }).join('');
}

function renderActivityList() {
    const activities = stores
        .flatMap(store =>
            (store.status_history ?? []).map(h => ({
                storeName: store.store_name || store.store_code,
                ...h,
            }))
        )
        .sort((a, b) => new Date(b.at) - new Date(a.at))
        .slice(0, 20);

    const container = document.getElementById('activityList');
    if (!activities.length) {
        container.innerHTML = '<div style="padding:18px;color:var(--text-muted);font-size:13px;">هنوز فعالیتی ثبت نشده</div>';
        return;
    }

    container.innerHTML = activities.map(({ storeName, from, to, at, note }) => {
        const toStatus  = getStatusObj(to);
        const fromLabel = from ? getStatusLabel(from) : 'جدید';
        const timeStr   = at ? new Date(at).toLocaleString('fa-IR', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) : '';
        return `
            <div class="activity-item">
                <div class="activity-dot" style="background:${toStatus.color}"></div>
                <div class="activity-text">
                    <strong>${esc(storeName)}</strong>: ${esc(fromLabel)} → ${esc(getStatusLabel(to))}
                    ${note ? `<br><span style="font-size:11px;color:var(--text-muted);">${esc(note)}</span>` : ''}
                </div>
                <div class="activity-time">${esc(timeStr)}</div>
            </div>
        `;
    }).join('');
}

function renderAlerts() {
    const alerts = stores.flatMap(store => {
        const days = daysInCurrentStage(store);
        const sla  = STAGE_SLA_DAYS[store.status];
        const result = [];

        if (sla && days > sla) {
            result.push({
                level: days > sla * 2 ? 'danger' : 'warn',
                text: `شعبه «${store.store_name || store.store_code}» ${days} روز در مرحله "${getStatusLabel(store.status)}" مانده (SLA: ${sla} روز، ${days - sla} روز تاخیر)`,
            });
        }
        return result;
    });

    const container = document.getElementById('alertsList');
    if (!alerts.length) {
        container.innerHTML = '<div style="padding:18px;color:var(--text-muted);font-size:13px;">✅ هشداری وجود ندارد</div>';
        return;
    }

    const iconPath = `<path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/><line x1="12" y1="9" x2="12" y2="13"/><line x1="12" y1="17" x2="12.01" y2="17"/>`;
    container.innerHTML = alerts.map(({ level, text }) => `
        <div class="alert-item ${level}">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="${level === 'danger' ? '#ef4444' : '#f59e0b'}" stroke-width="2">${iconPath}</svg>
            <span>${esc(text)}</span>
        </div>
    `).join('');
}

// Pipeline view
function renderPipeline() {
    const term = getSearchTerm();
    document.getElementById('pipelineBoard').innerHTML = STATUSES.map(status => {
        const statusStores = stores.filter(s => s.status === status.key && matchesSearch(s, term));
        const sla = STAGE_SLA_DAYS[status.key];

        const cards = statusStores.map(store => {
            const days = daysInCurrentStage(store);
            let daysColor = '';
            if (sla !== undefined) {
                const delay = days - sla;
                if (delay > 2) daysColor = 'color: #ef4444; font-weight: bold; animation: pulse 2s infinite;';
                else if (delay > 0 && delay <= 2) daysColor = 'color: #f59e0b; font-weight: bold;';
            }
            return `
                <div class="pipeline-card" onclick="openEditModal(${stores.indexOf(store)})">
                    <div class="pc-name">${esc(store.store_name || 'بدون نام')}</div>
                    <div class="pc-code">${esc(store.store_code)}</div>
                    ${store.city ? `<div class="pc-city">📍 ${esc(store.city)}</div>` : ''}
                    <div class="pc-days" style="${daysColor}">${days} روز در این مرحله${sla ? ` (SLA: ${sla} روز)` : ''}</div>
                </div>
            `;
        }).join('');

        return `
            <div class="pipeline-column">
                <div class="pipeline-column-header" style="border-top:3px solid ${status.color};">
                    <span>${esc(status.label)}</span>
                    <span class="col-count">${statusStores.length}</span>
                </div>
                <div class="pipeline-column-body">
                    ${cards || '<div style="text-align:center;color:var(--text-muted);font-size:12px;padding:20px;">خالی</div>'}
                </div>
            </div>
        `;
    }).join('');
}

// Table view
function renderTable() {
    const tbody       = document.getElementById('tableBody');
    const emptyState  = document.getElementById('emptyState');
    const tableWrapper = document.querySelector('.table-wrapper');
    const filtered    = getFilteredStores();

    if (!stores.length) {
        tbody.innerHTML = '';
        emptyState.style.display = 'flex';
        tableWrapper.style.display = 'none';
        return;
    }

    emptyState.style.display = 'none';
    tableWrapper.style.display = 'block';

    if (!filtered.length) {
        tbody.innerHTML = `<tr><td colspan="10" style="text-align:center;padding:30px;color:var(--text-muted);">نتیجه‌ای یافت نشد</td></tr>`;
        return;
    }

    tbody.innerHTML = filtered.map((store, fIdx) => {
        const realIndex  = stores.indexOf(store);
        const statusObj  = getStatusObj(store.status);
        const days       = daysInCurrentStage(store);
        const sla        = STAGE_SLA_DAYS[store.status];
        const daysBadge  = sla
            ? (days > sla ? 'days-danger' : days > sla * 0.7 ? 'days-warn' : 'days-ok')
            : 'days-ok';
        const createdDisplay = store.created_at
            ? new Date(store.created_at).toLocaleDateString('fa-IR')
            : '-';

        return `
            <tr>
                <td class="td-center">${fIdx + 1}</td>
                <td>
                    <span class="status-badge" style="background:${statusObj.color}22;color:${statusObj.color};">
                        <span class="status-dot" style="background:${statusObj.color}"></span>
                        ${esc(statusObj.label)}
                    </span>
                </td>
                <td>${esc(store.store_code)}</td>
                <td><strong>${esc(store.store_name)}</strong></td>
                <td>${esc(store.city)}</td>
                <td>${esc(store.state)}</td>
                <td>${esc(store.area_sqm || '-')}</td>
                <td>${esc(createdDisplay)}</td>
                <td><span class="days-badge ${daysBadge}">${days} روز</span></td>
                <td>
                    <div class="row-actions">
                        <button class="btn-icon edit" title="ویرایش" onclick="openEditModal(${realIndex})">
                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                                <path d="M11 4H4a2 2 0 00-2 2v14a2 2 0 002 2h14a2 2 0 002-2v-7"/>
                                <path d="M18.5 2.5a2.121 2.121 0 013 3L12 15l-4 1 1-4 9.5-9.5z"/>
                            </svg>
                        </button>
                        <button class="btn-icon delete" title="حذف" onclick="openDeleteModal(${realIndex})">
                            <svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                                <polyline points="3 6 5 6 21 6"/>
                                <path d="M19 6v14a2 2 0 01-2 2H7a2 2 0 01-2-2V6m3 0V4a2 2 0 012-2h4a2 2 0 012 2v2"/>
                            </svg>
                        </button>
                    </div>
                </td>
            </tr>
        `;
    }).join('');
}

const updateCount = () => {
    document.getElementById('totalCount').textContent = stores.length;
};

// Overview map
let activeMapFilter = 'ALL';

function renderOverviewMap() {
    const container = document.getElementById('overviewMapContainer');

    let filterBar = document.getElementById('mapFilterBar');
    if (!filterBar) {
        filterBar = document.createElement('div');
        filterBar.id = 'mapFilterBar';
        filterBar.style.cssText = `
            display:flex;flex-wrap:wrap;gap:6px;padding:10px 14px;
            background:var(--surface);border-bottom:1px solid var(--border);
            position:relative;z-index:10;
        `;
        container.parentElement.insertBefore(filterBar, container);

        const makeMapTab = (label, key) => {
            const btn = document.createElement('button');
            btn.className = 'status-filter-tab' + (key === 'ALL' ? ' active' : '');
            btn.textContent = label;
            btn.dataset.mapStatus = key;
            btn.addEventListener('click', () => {
                activeMapFilter = key;
                document.querySelectorAll('[data-map-status]').forEach(b =>
                    b.classList.toggle('active', b.dataset.mapStatus === key)
                );
                renderMapMarkers();
            });
            return btn;
        };

        filterBar.append(
            makeMapTab('همه', 'ALL'),
            ...STATUSES.map(s => makeMapTab(s.label, s.key))
        );
    }

    if (!overviewMap) {
        overviewMap = new L.Map(container, {
            key: NESHAN_MAP_KEY, maptype: 'neshan',
            poi: false, traffic: false,
            center: [35.6892, 51.3890], zoom: 6,
        });
    }

    renderMapMarkers();
}

function renderMapMarkers() {
    overviewMarkers.forEach(m => overviewMap.removeLayer(m));
    overviewMarkers = [];

    const filtered = stores.filter(s =>
        activeMapFilter === 'ALL' || s.status === activeMapFilter
    );

    filtered.forEach((store, _) => {
        const realIndex = stores.indexOf(store);
        const lat = parseFloat(store.lat);
        const lng = parseFloat(store.lng);
        if (isNaN(lat) || isNaN(lng)) return;

        const { color, label: statusLabel } = getStatusObj(store.status);
        const sla  = STAGE_SLA_DAYS[store.status];
        const days = daysInCurrentStage(store);
        
        const delay = days - (sla !== undefined ? sla : 999);
        const isWarning = delay > 0 && delay <= 2;
        const isDanger  = delay > 2;

        const icon = L.divIcon({
            className: 'custom-marker',
            html: `
                <div style="position:relative;width:18px;height:18px;">
                    <div style="
                        width:14px;height:14px;border-radius:50%;
                        background:${color};border:2px solid #fff;
                        box-shadow:0 2px 8px rgba(0,0,0,0.45);
                        position:absolute;top:2px;left:2px;
                    "></div>
                    ${isDanger ? `<div style="
                        position:absolute;top:0;left:0;
                        width:18px;height:18px;border-radius:50%;
                        border:2px solid #ef4444;
                        animation:ping 1.2s ease-in-out infinite;
                        opacity:.7;
                    "></div>` : (isWarning ? `<div style="
                        position:absolute;top:0;left:0;
                        width:18px;height:18px;border-radius:50%;
                        border:2px solid #f59e0b;
                        opacity:.8;
                    "></div>` : '')}
                </div>`,
            iconSize: [18, 18], iconAnchor: [9, 9],
        });

        const marker = L.marker([lat, lng], { icon }).addTo(overviewMap);

        const daysBadgeColor = isDanger ? '#ef4444' : days > (sla ?? 999) * 0.7 ? '#f59e0b' : '#10b981';

        marker.bindPopup(`
            <div style="
                direction:rtl;font-family:Vazirmatn,sans-serif;
                font-size:13px;min-width:220px;max-width:280px;
                line-height:1.7;
            ">
                <div style="
                    display:flex;align-items:center;justify-content:space-between;
                    margin-bottom:8px;padding-bottom:8px;
                    border-bottom:1px solid #e5e7eb;
                ">
                    <strong style="font-size:14px;">${esc(store.store_name || 'بدون نام')}</strong>
                    <span style="
                        background:${color}22;color:${color};
                        font-size:11px;font-weight:600;padding:2px 8px;
                        border-radius:20px;border:1px solid ${color}44;
                    ">${esc(statusLabel)}</span>
                </div>

                <table style="width:100%;font-size:12px;border-collapse:collapse;">
                    <tr>
                        <td style="color:#6b7280;padding:2px 0;width:40%;">کد شعبه</td>
                        <td style="font-weight:600;">${esc(store.store_code || '-')}</td>
                    </tr>
                    ${store.city ? `<tr>
                        <td style="color:#6b7280;padding:2px 0;">شهر</td>
                        <td>📍 ${esc(store.city)}${store.state ? ` — ${esc(store.state)}` : ''}</td>
                    </tr>` : ''}
                    ${store.formatted_address ? `<tr>
                        <td style="color:#6b7280;padding:2px 0;">آدرس</td>
                        <td style="font-size:11px;color:#374151;">${esc(store.formatted_address)}</td>
                    </tr>` : ''}
                    ${store.area_manager ? `<tr>
                        <td style="color:#6b7280;padding:2px 0;">مدیر منطقه</td>
                        <td>${esc(store.area_manager)}</td>
                    </tr>` : ''}
                    ${store.development_expert ? `<tr>
                        <td style="color:#6b7280;padding:2px 0;">کارشناس</td>
                        <td>${esc(store.development_expert)}</td>
                    </tr>` : ''}
                    <tr>
                        <td style="color:#6b7280;padding:2px 0;">مدت در مرحله</td>
                        <td>
                            <span style="
                                color:${daysBadgeColor};font-weight:600;
                            ">${days} روز${sla ? ` / SLA: ${sla} روز` : ''}</span>
                        </td>
                    </tr>
                    ${store.is_franchise === '1' || store.is_franchise === true ? `<tr>
                        <td style="color:#6b7280;padding:2px 0;">نوع</td>
                        <td><span style="color:#8b5cf6;font-weight:600;">فرانچایز</span></td>
                    </tr>` : ''}
                </table>

                <div style="margin-top:10px;padding-top:8px;border-top:1px solid #e5e7eb;text-align:left;">
                    <button onclick="closePopups();openEditModal(${realIndex})" style="
                        background:#3b82f6;color:#fff;border:none;
                        padding:5px 14px;border-radius:6px;cursor:pointer;
                        font-family:Vazirmatn,sans-serif;font-size:12px;font-weight:600;
                    ">✏️ ویرایش</button>
                </div>
            </div>
        `, { maxWidth: 300 });

        overviewMarkers.push(marker);
    });

    if (overviewMarkers.length) {
        overviewMap.fitBounds(L.featureGroup(overviewMarkers).getBounds().pad(0.15));
    }
}

const closePopups = () => overviewMap?.closePopup();

// Performance view
function renderPerformance() {
    const total = stores.length || 1;

    const barRows = (rows) => rows.map(({ label, pct, color, valueText }) => `
        <div class="perf-bar-row">
            <div class="perf-bar-label">${esc(label)}</div>
            <div class="perf-bar-track">
                <div class="perf-bar-fill" style="width:${pct}%;background:${color};"></div>
            </div>
            <div class="perf-bar-value">${esc(valueText)}</div>
        </div>
    `).join('');

    const perfCard = (title, innerHtml) =>
        `<div class="perf-card"><h4>${title}</h4>${innerHtml}</div>`;

    const distRows = STATUSES.map(s => {
        const count = stores.filter(st => st.status === s.key).length;
        return { label: s.label, pct: Math.round(count / total * 100), color: s.color, valueText: `${count} (${Math.round(count / total * 100)}%)` };
    });

    const avgRows = STATUSES.map(s => {
        const group = stores.filter(st => st.status === s.key);
        if (!group.length) return { label: s.label, pct: 0, color: s.color, valueText: '-' };
        const avg = Math.round(group.reduce((sum, st) => sum + daysInCurrentStage(st), 0) / group.length);
        const sla = STAGE_SLA_DAYS[s.key] ?? 90;
        const color = avg > sla ? 'var(--danger)' : avg > sla * 0.7 ? 'var(--warning)' : s.color;
        return { label: s.label, pct: Math.min(Math.round(avg / sla * 100), 100), color, valueText: `${avg} روز` };
    });

    const cityCounts = {};
    stores.forEach(s => { const c = s.city || 'نامشخص'; cityCounts[c] = (cityCounts[c] || 0) + 1; });
    const cityRows = Object.entries(cityCounts)
        .sort((a, b) => b[1] - a[1])
        .slice(0, 10)
        .map(([city, count]) => ({ label: city, pct: Math.round(count / total * 100), color: 'var(--accent)', valueText: String(count) }));

    const violations = stores.filter(s => {
        const sla = STAGE_SLA_DAYS[s.status];
        return sla && daysInCurrentStage(s) > sla;
    });
    const violationsHtml = violations.map(s => {
        const delay = daysInCurrentStage(s) - STAGE_SLA_DAYS[s.status];
        return `<div style="display:flex;justify-content:space-between;padding:6px 0;border-bottom:1px solid var(--border);font-size:12px;">
            <span>${esc(s.store_name || s.store_code)} — ${esc(getStatusLabel(s.status))}</span>
            <span style="color:var(--danger);font-weight:600;">${delay}+ روز تاخیر</span>
        </div>`;
    }).join('');

    const cards = [
        perfCard('توزیع وضعیت‌ها', barRows(distRows)),
        perfCard('میانگین روز در هر مرحله', barRows(avgRows)),
        ...(stores.length ? [perfCard('توزیع شهری (۱۰ شهر برتر)', barRows(cityRows))] : []),
        ...(violations.length ? [perfCard(`نقض SLA (${violations.length} مورد)`, violationsHtml)] : []),
    ];

    document.getElementById('perfGrid').innerHTML = cards.join('');
}

// Issues view
function renderIssues() {
    const PRIORITY_ORDER = { critical: 0, high: 1, medium: 2, low: 3 };

    const allIssues = stores
        .flatMap(store => (store.issues ?? []).map(issue => ({
            ...issue,
            storeName: store.store_name || store.store_code,
        })))
        .sort((a, b) => (PRIORITY_ORDER[a.priority] ?? 3) - (PRIORITY_ORDER[b.priority] ?? 3));

    const container = document.getElementById('issuesList');
    if (!allIssues.length) {
        container.innerHTML = '<div style="padding:40px;text-align:center;color:var(--text-muted);">مشکلی ثبت نشده ✅</div>';
        return;
    }

    container.innerHTML = allIssues.map(issue => `
        <div class="issue-item">
            <div class="issue-priority ${esc(issue.priority)}"></div>
            <div class="issue-info">
                <div class="issue-title">${esc(issue.title)}</div>
                <div class="issue-meta">${esc(issue.storeName)} • ${esc(issue.description || '')} • ${formatDaysAgo(issue.created_at)}</div>
            </div>
            <span class="issue-status-badge ${issue.status === 'resolved' ? 'resolved' : 'open'}">
                ${issue.status === 'resolved' ? 'حل شده' : 'باز'}
            </span>
        </div>
    `).join('');
}

// Issue modal
function openIssueModal() {
    const sel = document.getElementById('issueStoreSelect');
    sel.innerHTML = '<option value="">انتخاب شعبه...</option>' +
        stores.map((s, i) => `<option value="${i}">${esc(s.store_name || s.store_code)}</option>`).join('');

    ['issueTitle', 'issueDescription'].forEach(id => document.getElementById(id).value = '');
    document.getElementById('issuePriority').value = 'medium';
    document.getElementById('issueOverlay').classList.add('open');
}

const closeIssueModal = () => document.getElementById('issueOverlay').classList.remove('open');

function saveIssue() {
    const storeIdx   = parseInt(document.getElementById('issueStoreSelect').value);
    const title      = document.getElementById('issueTitle').value.trim();
    const priority   = document.getElementById('issuePriority').value;
    const description = document.getElementById('issueDescription').value.trim();

    if (isNaN(storeIdx) || !stores[storeIdx]) { showToast('لطفاً شعبه مرتبط را انتخاب کنید', 'error'); return; }
    if (!title)                               { showToast('عنوان مشکل الزامی است', 'error'); return; }

    (stores[storeIdx].issues ??= []).push({
        id: generateId(), title, priority, description,
        status: 'open', created_at: nowISO(), resolved_at: '', 
    });

    saveToStorage(stores[storeIdx]);
    closeIssueModal();
    renderIssues();
    showToast('مشکل ثبت شد', 'success');
}

// Add/Edit modal
const FORM_FIELD_MAP = {
    inputStatus:           'status',
    inputStoreCode:        'store_code',
    inputStoreName:        'store_name',
    inputPropertyType:     'property_type',
    inputAreaManager:        'area_manager',
    inputDevelopmentExpert:  'development_expert',
    inputArea:             'area_sqm',
    inputRentOwn:          'rent_or_own',
    inputMonthlyRent:      'monthly_rent',
    inputOwnerName:        'owner_name',
    inputOwnerPhone:       'owner_phone',
    inputIsFranchise:      'is_franchise',
    inputContractDuration: 'contract_duration',
    inputLat:              'lat',
    inputLng:              'lng',
    inputAddress:          'formatted_address',
    inputCity:             'city',
    inputState:            'state',
    inputCounty:           'county',
    inputDistrict:         'district',
    inputVillage:          'village',
    inputMunicipalityZone: 'municipality_zone',
    inputTrafficZone:      'in_traffic_zone',
    inputOddEvenZone:      'in_odd_even_zone',
};

function populateStatusSelect() {
    document.getElementById('inputStatus').innerHTML = STATUSES
        .map(s => `<option value="${s.key}">${s.label}</option>`)
        .join('');
}

function setFormFromStore(store) {
    Object.entries(FORM_FIELD_MAP).forEach(([inputId, storeKey]) => {
        const el = document.getElementById(inputId);
        if (el) el.value = store[storeKey] ?? '';
    });
    document.getElementById('inputStatusNote').value = '';
    document.getElementById('inputNote').value = '';
}

function clearForm() {
    Object.keys(FORM_FIELD_MAP).forEach(id => {
        const el = document.getElementById(id);
        if (el) el.value = el.tagName === 'SELECT' ? el.options[0]?.value ?? '' : '';
    });
    geoFetched = false;
    document.getElementById('inputStatus').value = 'location_sent';
    document.getElementById('inputTrafficZone').value  = 'FALSE';
    document.getElementById('inputOddEvenZone').value  = 'FALSE';
    document.getElementById('inputIsFranchise').value  = '0';
    document.getElementById('inputStatusNote').value   = '';
    document.getElementById('inputNote').value         = '';
    document.getElementById('fetchStatus').textContent = '';
    document.getElementById('fetchStatus').className   = 'fetch-status';
}

function openAddModal() {
    editingIndex = -1;
    document.getElementById('modalTitle').textContent = 'افزودن شعبه جدید';
    document.getElementById('btnSave').textContent    = 'ذخیره';
    clearForm();
    needsAddressFetch = false;
    
    const overlay = document.getElementById('map-lock-overlay');
    if(overlay) overlay.classList.add('hidden');

    document.getElementById('sectionHistory').style.display = 'none';
    document.getElementById('modalOverlay').classList.add('open');
    setTimeout(() => initModalMap(), 200);
}

function openEditModal(index) {
    const store = stores[index];
    if (!store) return;

    editingIndex = index;
    document.getElementById('modalTitle').textContent = `ویرایش شعبه: ${store.store_name || store.store_code}`;
    document.getElementById('btnSave').textContent    = 'بروزرسانی';

    setFormFromStore(store);
    needsAddressFetch = false;

    const hasHistory = store.status_history?.length;
    document.getElementById('sectionHistory').style.display = hasHistory ? 'block' : 'none';
    if (hasHistory) renderStatusTimeline(store.status_history);

    document.getElementById('modalOverlay').classList.add('open');
    setTimeout(() => {
        initModalMap();
        const lat = parseFloat(store.lat);
        const lng = parseFloat(store.lng);
        
        const overlay = document.getElementById('map-lock-overlay');
        
        if (!isNaN(lat) && !isNaN(lng)) {
            modalMap.setView([lat, lng], 15);
            placeModalMarker(lat, lng);
            if(overlay) overlay.classList.remove('hidden');
        } else {
            if(overlay) overlay.classList.add('hidden');
        }
    }, 200);
}

const closeModal = () => {
    document.getElementById('modalOverlay').classList.remove('open');
    editingIndex = -1;
};

function renderStatusTimeline(history) {
    document.getElementById('statusTimeline').innerHTML = [...history].reverse().map(h => {
        const fromLabel = h.from ? getStatusLabel(h.from) : 'شروع';
        const timeStr   = h.at ? new Date(h.at).toLocaleString('fa-IR', { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }) : '';
        return `
            <div class="timeline-item">
                <div class="tl-time">${esc(timeStr)}</div>
                <div class="tl-text">${esc(fromLabel)} → <strong>${esc(getStatusLabel(h.to))}</strong></div>
                ${h.note ? `<div class="tl-note">"${esc(h.note)}"</div>` : ''}
            </div>
        `;
    }).join('');
}

// Modal map initialization
function initModalMap() {
    if (!document.getElementById('mapContainer')) return;
    if (modalMap) { modalMap.invalidateSize(); return; }

    modalMap = new L.Map('mapContainer', {
        key: NESHAN_MAP_KEY, maptype: 'neshan',
        poi: false, traffic: false,
        center: [35.6892, 51.3890], zoom: 12,
    });

    modalMap.on('click', ({ latlng: { lat, lng } }) => {
        document.getElementById('inputLat').value = lat.toFixed(6);
        document.getElementById('inputLng').value = lng.toFixed(6);
        placeModalMarker(lat, lng);
        needsAddressFetch = true;
    });
}

function placeModalMarker(lat, lng) {
    if (modalMarker) modalMap.removeLayer(modalMarker);
    modalMarker = L.marker([lat, lng]).addTo(modalMap);
}

// Reverse geocode address information
async function fetchGeoInfo() {
    const lat = document.getElementById('inputLat').value.trim();
    const lng = document.getElementById('inputLng').value.trim();
    const statusEl = document.getElementById('fetchStatus');

    if (!lat || !lng) { showToast('ابتدا مختصات را وارد کنید یا روی نقشه کلیک کنید', 'error'); return false; }

    statusEl.textContent = 'در حال دریافت...';
    statusEl.className   = 'fetch-status loading';

    try {
        const res = await fetch(`https://api.neshan.org/v5/reverse?lat=${lat}&lng=${lng}`, {
            headers: { 'Api-Key': API_KEY_DEFAULT },
        });
        if (!res.ok) throw new Error(`HTTP ${res.status}`);
        const data = await res.json();

        const GEO_MAP = {
            formatted_address: 'inputAddress',
            city:              'inputCity',
            state:             'inputState',
            county:            'inputCounty',
            district:          'inputDistrict',
            village:           'inputVillage',
            municipality_zone: 'inputMunicipalityZone',
        };
        Object.entries(GEO_MAP).forEach(([key, inputId]) => {
            if (data[key]) document.getElementById(inputId).value = data[key];
        });
        if (data.in_traffic_zone !== undefined)
            document.getElementById('inputTrafficZone').value = data.in_traffic_zone ? 'TRUE' : 'FALSE';
        if (data.in_odd_even_zone !== undefined)
            document.getElementById('inputOddEvenZone').value = data.in_odd_even_zone ? 'TRUE' : 'FALSE';

        statusEl.textContent = '✅ دریافت شد';
        statusEl.className   = 'fetch-status success';
        geoFetched = true;  
        needsAddressFetch = false; 
        
        return true; 

    } catch (err) {
        console.error(err);
        statusEl.textContent = '❌ خطا در دریافت';
        statusEl.className   = 'fetch-status error';
        showToast(`خطا در دریافت اطلاعات: ${err.message}`, 'error');
        return false;
    }
}

// Save store data
function getFormValues() {
    const get = id => document.getElementById(id)?.value?.trim() ?? '';
    return {
        status:            get('inputStatus'),
        statusNote:        get('inputStatusNote'),
        store_code:        get('inputStoreCode'),
        store_name:        get('inputStoreName'),
        area_manager:      get('inputAreaManager'),        
        development_expert: get('inputDevelopmentExpert'), 
        lat:               get('inputLat'),
        lng:               get('inputLng'),
        formatted_address: get('inputAddress'),
        city:              get('inputCity'),
        state:             get('inputState'),
        county:            get('inputCounty'),
        district:          get('inputDistrict'),
        village:           get('inputVillage'),
        municipality_zone: get('inputMunicipalityZone'),
        in_traffic_zone:   get('inputTrafficZone'),
        in_odd_even_zone:  get('inputOddEvenZone'),
        is_franchise:      get('inputIsFranchise'),
        property_type:     get('inputPropertyType'),
        area_sqm:          get('inputArea'),
        rent_or_own:       get('inputRentOwn'),
        monthly_rent:      get('inputMonthlyRent'),
        contract_duration: get('inputContractDuration'),
        owner_name:        get('inputOwnerName'),
        owner_phone:       get('inputOwnerPhone'),
        note:              get('inputNote'),
    };
}

async function saveStore() {
    let form = getFormValues(); 

    if (!form.store_code) { showToast('کد شعبه الزامی است', 'error'); return; }
    if (!form.store_name) { showToast('نام شعبه الزامی است', 'error'); return; }
    if (!form.lat || !form.lng) { showToast('مختصات جغرافیایی الزامی است', 'error'); return; }

    if (stores.some((s, i) => s.store_code === form.store_code && i !== editingIndex)) {
        showToast('کد شعبه تکراری است', 'error'); return;
    }

    if (needsAddressFetch) {
        const btnSave = document.getElementById('btnSave');
        const originalText = btnSave.textContent;
        btnSave.textContent = 'در حال دریافت اطلاعات آدرس...';
        btnSave.disabled = true;

        const success = await fetchGeoInfo();

        btnSave.textContent = originalText;
        btnSave.disabled = false;

        if (!success) {
            showToast('ذخیره متوقف شد: اینترنت خود را بررسی کنید', 'error');
            return;
        }

        form = getFormValues(); 
    }

    let storeToSave = null;

    if (editingIndex === -1) {
        storeToSave = {
            id: generateId(),
            ...form,
            created_at:     nowISO(),
            updated_at:     nowISO(),
            status_history: [{ from: null, to: form.status, at: nowISO(), note: form.statusNote || 'ثبت اولیه' }],
            notes:   form.note ? [{ text: form.note, at: nowISO() }] : [],
            issues:  [],
        };
        delete storeToSave.statusNote;
        delete storeToSave.note;
        stores.push(storeToSave);
        showToast('شعبه جدید ثبت شد ✅', 'success');

    } else {
        storeToSave = stores[editingIndex];
        const oldStatus = storeToSave.status;

        Object.assign(storeToSave, form, { updated_at: nowISO() });
        delete storeToSave.statusNote;
        delete storeToSave.note;

        if (form.status !== oldStatus) {
            (storeToSave.status_history ??= []).push({
                from: oldStatus, to: form.status,
                at: nowISO(), note: form.statusNote || '',
            });
        }
        if (form.note) {
            (storeToSave.notes ??= []).push({ text: form.note, at: nowISO() });
        }
        showToast('شعبه بروزرسانی شد ✅', 'success');
    }

    saveToStorage(storeToSave);
    closeModal();
    refreshAllViews();
}

// Delete modal
function openDeleteModal(index) {
    const store = stores[index];
    if (!store) return;
    document.getElementById('deleteStoreName').textContent = store.store_name || store.store_code;
    document.getElementById('deleteOverlay').classList.add('open');
    
    document.getElementById('btnDeleteConfirm').onclick = () => {
        store.is_deleted = true;
        store.updated_at = nowISO();
        
        saveToStorage(store); 
        
        stores.splice(index, 1);
        
        closeDeleteModal();
        refreshAllViews();
        showToast('شعبه با موفقیت حذف شد', 'warning');
    };
}

const closeDeleteModal = () => document.getElementById('deleteOverlay').classList.remove('open');

// Refresh all views after data changes
function refreshAllViews() {
    updateCount();
    renderDashboard();
    renderTable();

    const activeViewRenderers = {
        viewPipeline:     renderPipeline,
        viewPerformance:  renderPerformance,
        viewIssues:       renderIssues,
        viewMapOverview:  renderOverviewMap,
    };
    Object.entries(activeViewRenderers).forEach(([id, fn]) => {
        if (document.getElementById(id)?.classList.contains('active')) fn();
    });
}

// CSV export utilities
const csvEscape = (val) => {
    const str = String(val ?? '');
    return /[,"\n\r]/.test(str) ? `"${str.replace(/"/g, '""')}"` : str;
};

const normalizeBool = (val) =>
    (val === true || val === 'TRUE' || val === 'true') ? 'TRUE' : 'FALSE';

const normalizeFranchise = (val) =>
    (val === true || val === '1' || val === 1) ? '1' : '0';

function exportCSV() {
    window.location.href = 'api.php?action=download_csv';
    showToast('دانلود فایل CSV شروع شد', 'success');
}

function renderExportPreview() {
    const preview = document.getElementById('csvPreview');
    if (!stores.length) { preview.textContent = '(هنوز داده‌ای ثبت نشده)'; return; }

    const sampleRows = stores.slice(0, 3).map(store =>
        CSV_FIELDS.map(field => {
            let val = store[field];
            if (field === 'in_traffic_zone' || field === 'in_odd_even_zone')
                val = normalizeBool(val) === 'TRUE' ? 'بله' : 'خیر';
            if (field === 'is_franchise')
                val = normalizeFranchise(val) === '1' ? 'دارد' : 'ندارد';
            if (field === 'status')
                val = getStatusLabel(val || 'REGISTERED');
            return csvEscape(val);
        }).join(',')
    );
    preview.textContent = CSV_FIELDS.join(',') + '\n' + sampleRows.join('\n');
}

function exportJSON() {
    if (!stores.length) {
        showToast('داده‌ای برای دانلود وجود ندارد', 'error');
        return;
    }
    const dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(stores, null, 2));
    const downloadAnchorNode = document.createElement('a');
    downloadAnchorNode.setAttribute("href", dataStr);
    downloadAnchorNode.setAttribute("download", "stores_backup.json");
    document.body.appendChild(downloadAnchorNode);
    downloadAnchorNode.click();
    downloadAnchorNode.remove();
    showToast('فایل پشتیبان JSON دانلود شد', 'success');
}
