"""مطابقة أوردرات إيزي أوردر (المصدر/UTM) مع أوردرات كذا ميزا أو فيندور.

المفتاح: الموبايل (آخر 10 أرقام) + التاريخ (± يومين) + الإجمالي كتأكيد.
"""

import json
import os
import re
from datetime import datetime

import easy_orders
import orders_import

DATA_DIR = os.path.dirname(os.path.abspath(__file__))

_CACHE = {}


def _cache_key(target, month, start, end):
    return (target, month or 'الكل', start or '', end or '')


def norm_phone(value):
    digits = re.sub(r'\D', '', str(value or ''))
    if not digits:
        return ''
    if digits.startswith('0020'):
        digits = digits[4:]
    elif digits.startswith('20') and len(digits) >= 12:
        digits = digits[2:]
    while digits.startswith('0') and len(digits) > 10:
        digits = digits[1:]
    return digits[-10:]


def _date(value):
    try:
        return datetime.strptime(value, '%d-%m-%Y')
    except (TypeError, ValueError):
        return None


def _num(value):
    try:
        return float(str(value or '0').replace(',', ''))
    except ValueError:
        return 0.0


def _month_match(date_str, month):
    return not month or month == 'الكل' or (date_str or '').endswith(f'-{month}')


def _month_match(date_str, month):
    return not month or month == 'الكل' or (date_str or '').endswith(f'-{month}')


def _in_range(date_str, month='الكل', start=None, end=None):
    if start and end:
        try:
            d = datetime.strptime(date_str or '', '%d-%m-%Y').date()
            s = datetime.strptime(start, '%Y-%m-%d').date()
            e = datetime.strptime(end, '%Y-%m-%d').date()
            return s <= d <= e
        except ValueError:
            return False
    return _month_match(date_str, month)


def match(target, month='الكل', start=None, end=None):
    key = _cache_key(target, month, start, end)
    if key in _CACHE:
        return _CACHE[key]
    easy = easy_orders.load()
    if target == 'vendor':
        rows = orders_import.load_orders('vendor')
        id_key, phone_key, date_key = 'رقم الطلب', 'رقم العميل', 'تاريخ الإنشاء'
    else:
        rows = orders_import.load_orders('kzamiza')
        id_key, phone_key, date_key = 'رقم الطلب', 'رقم العميل', 'تاريخ الإنشاء'

    by_phone = {}
    for order in easy:
        key = norm_phone(order.get('phone'))
        if key:
            by_phone.setdefault(key, []).append(order)

    used = set()
    results = {}
    stats = {'total': 0, 'matched': 0, 'high': 0, 'medium': 0, 'low': 0, 'unmatched': 0}
    by_source = {}

    for row in rows:
        if not _in_range(row.get(date_key), month, start, end):
            continue
        phone = norm_phone(row.get(phone_key))
        if not phone:
            continue
        order_date = _date(row.get(date_key))
        if not order_date:
            continue
        stats['total'] += 1
        candidates = [o for o in by_phone.get(phone, []) if o['id'] not in used]
        best, best_score, best_kind = None, None, None
        total_value = _num(row.get('الإجمالي'))

        for cand in candidates:
            cand_date = _date(cand.get('date'))
            if not cand_date:
                continue
            days = abs((cand_date - order_date).days)
            if days > 2:
                continue
            diff = abs(_num(cand.get('total')) - total_value)
            score = (days, diff)
            if best_score is None or score < best_score:
                best, best_score, best_kind = cand, score, days

        if not best:
            stats['unmatched'] += 1
            results[row.get(id_key)] = {'match': None}
            continue

        days, diff = best_score
        if days == 0 and diff <= 1:
            kind = 'high'
        elif days == 0:
            kind = 'medium'
        else:
            kind = 'low'

        if kind == 'low':
            stats['low'] += 1
            results[row.get(id_key)] = {'match': None, 'reason': 'low_confidence'}
            continue

        stats[kind] += 1
        stats['matched'] += 1
        used.add(best['id'])
        source = best.get('utm_source') or 'direct'
        by_source[source] = by_source.get(source, 0) + 1
        results[row.get(id_key)] = {
            'easy_id': best['id'],
            'source': source,
            'campaign': best.get('utm_campaign') or '',
            'confidence': kind,
            'date_diff': days,
            'total_diff': round(diff, 2),
        }

    stats['by_source'] = by_source
    stats['sources_available'] = easy_orders.summary().get('sources', {})
    result = {'stats': stats, 'matches': results}
    _CACHE[key] = result
    return result


def save(target, data):
    path = os.path.join(DATA_DIR, f'attribution_{target}.json')
    with open(path, 'w', encoding='utf-8') as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
    return path


def load(target):
    path = os.path.join(DATA_DIR, f'attribution_{target}.json')
    if not os.path.exists(path):
        return {}
    with open(path, 'r', encoding='utf-8') as f:
        return json.load(f)
