"""
台灣不動產估價師 CRM - 主程式

整合抓取、變更偵測、報告產生、通知發送
"""
import sys
sys.stdout.reconfigure(encoding='utf-8')

import argparse
import time
import json
from datetime import datetime
from pathlib import Path

import csv

from database import init_database, get_total_appraisers, get_appraiser_count_by_association, cleanup_old_snapshots, get_snapshot_stats
from scraper import SCRAPERS
from detector import process_scrape_result, get_changes_summary

# CSV 檔案對照
CSV_FILES = {
    'taipei': 'taipei_appraisers.csv',
    'newtaipei': 'newtaipei_appraisers.csv',
    'taoyuan': 'taoyuan_appraisers.csv',
    'taichung': 'taichung_appraisers.csv',
    'tainan': 'tainan_appraisers.csv',
    'kaohsiung': 'kaohsiung_appraisers.csv',
}

def read_csv_file(filename):
    """讀取 CSV 檔案"""
    filepath = Path(__file__).parent / filename
    if not filepath.exists():
        return []

    for encoding in ['utf-8-sig', 'utf-8', 'cp950']:
        try:
            with open(filepath, 'r', encoding=encoding) as f:
                return list(csv.DictReader(f))
        except UnicodeDecodeError:
            continue

    return []
from reporter import (
    generate_text_report, generate_json_report, generate_telegram_message,
    send_telegram_notification, save_report
)

# 公會名稱對照
ASSOCIATION_MAP = {
    'taipei': '台北市',
    'newtaipei': '新北市',
    'taoyuan': '桃園市',
    'taichung': '台中市',
    'tainan': '台南市',
    'kaohsiung': '高雄市',
}

def run_scrape_and_detect(notify=True, verbose=True):
    """
    執行抓取並偵測變更

    Args:
        notify: 是否發送 Telegram 通知
        verbose: 是否顯示詳細輸出

    Returns:
        dict: 執行結果
    """
    init_database()

    if verbose:
        print('=' * 50)
        print('開始抓取估價師名冊...')
        print('=' * 50)

    start_time = time.time()

    # 執行抓取
    update_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    scrape_results = {}

    for code, (assoc_name, scraper_func) in SCRAPERS.items():
        if code in ['associations', 'ctreaa']:  # 跳過全聯會和中台灣（理監事）
            continue

        if code not in CSV_FILES:
            continue

        if verbose:
            print(f'\n抓取 {assoc_name}...')

        try:
            # 執行抓取（會輸出 CSV 檔案）
            scraper_func(update_time)

            # 讀取生成的 CSV 檔案
            csv_file = CSV_FILES[code]
            data = read_csv_file(csv_file)
            scrape_results[code] = data

            if verbose:
                print(f'  取得 {len(data)} 筆')
        except Exception as e:
            print(f'  錯誤: {e}')
            scrape_results[code] = []

    scrape_duration = time.time() - start_time

    # 偵測變更
    if verbose:
        print('\n' + '=' * 50)
        print('偵測變更...')
        print('=' * 50)

    all_results = []

    for code, data in scrape_results.items():
        association = ASSOCIATION_MAP.get(code, code)

        if not data:
            all_results.append({
                'association': association,
                'record_count': 0,
                'has_changes': False,
                'changes': None,
            })
            continue

        result = process_scrape_result(code, data, association)
        all_results.append(result)

        if verbose:
            summary = get_changes_summary(result.get('changes'))
            status = '有變更' if result['has_changes'] else '無變更'
            print(f'  {association}: {result["record_count"]} 筆 - {status}')
            if result['has_changes']:
                print(f'    → {summary}')

    # 產生報告
    if verbose:
        print('\n' + '=' * 50)
        print('產生報告...')
        print('=' * 50)

    text_report = generate_text_report(all_results, scrape_duration)
    json_report = generate_json_report(all_results, scrape_duration)

    # 儲存報告
    report_path = save_report(json_report)

    # 判斷是否有變更
    has_any_changes = any(r['has_changes'] for r in all_results)

    # 發送通知
    if notify and has_any_changes:
        if verbose:
            print('\n發送 Telegram 通知...')

        telegram_msg = generate_telegram_message(all_results)
        if telegram_msg:
            send_telegram_notification(telegram_msg)
    elif notify and not has_any_changes:
        if verbose:
            print('\n無變更，不發送通知')

    # 清理超過 30 天的舊快照
    cleanup_old_snapshots(days=30)

    # 顯示文字報告
    if verbose:
        print('\n')
        print(text_report)

    return {
        'success': True,
        'duration': scrape_duration,
        'has_changes': has_any_changes,
        'results': all_results,
        'report_path': str(report_path),
    }

def cmd_scrape(args):
    """scrape 指令"""
    result = run_scrape_and_detect(
        notify=not args.no_notify,
        verbose=not args.quiet
    )
    return 0 if result['success'] else 1

def cmd_stats(args):
    """stats 指令"""
    init_database()

    total = get_total_appraisers()
    by_assoc = get_appraiser_count_by_association()

    print(f'\n估價師總數: {total}')
    print('\n各公會人數:')
    for assoc, count in sorted(by_assoc.items(), key=lambda x: -x[1]):
        print(f'  {assoc}: {count}')
    print()

    return 0

def cmd_search(args):
    """search 指令"""
    from database import get_connection

    init_database()
    conn = get_connection()
    cursor = conn.cursor()

    query = f'%{args.query}%'

    cursor.execute('''
        SELECT a.name, a.status, ch.association, ch.office_name, ch.phone
        FROM appraisers a
        LEFT JOIN career_history ch ON a.id = ch.appraiser_id AND ch.is_current = 1
        WHERE a.name LIKE ? OR ch.office_name LIKE ?
        ORDER BY a.name
    ''', (query, query))

    results = cursor.fetchall()
    conn.close()

    if not results:
        print(f'找不到符合「{args.query}」的結果')
        return 1

    print(f'\n找到 {len(results)} 筆結果:\n')
    for r in results:
        status = '' if r['status'] == 'active' else f" [{r['status']}]"
        print(f"  {r['name']}{status}")
        print(f"    公會: {r['association'] or '?'}")
        print(f"    事務所: {r['office_name'] or '?'}")
        if r['phone']:
            print(f"    電話: {r['phone']}")
        print()

    return 0

def cmd_export(args):
    """export 指令"""
    import csv
    from database import get_all_appraisers

    init_database()
    appraisers = get_all_appraisers()

    output_path = args.output or 'appraisers_export.csv'

    with open(output_path, 'w', encoding='utf-8-sig', newline='') as f:
        writer = csv.DictWriter(f, fieldnames=[
            'name', 'association', 'office_name', 'office_address', 'phone',
            'license_number', 'status', 'first_seen_date', 'last_seen_date'
        ])
        writer.writeheader()

        for a in appraisers:
            writer.writerow({
                'name': a['name'],
                'association': a.get('association', ''),
                'office_name': a.get('office_name', ''),
                'office_address': a.get('office_address', ''),
                'phone': a.get('phone', ''),
                'license_number': a.get('license_number', ''),
                'status': a['status'],
                'first_seen_date': a['first_seen_date'],
                'last_seen_date': a['last_seen_date'],
            })

    print(f'已匯出 {len(appraisers)} 筆到 {output_path}')
    return 0

def cmd_report(args):
    """report 指令 - 顯示最近的變更報告"""
    from database import get_changes_by_date

    init_database()
    date = args.date or datetime.now().strftime('%Y-%m-%d')

    changes = get_changes_by_date(date)

    if not changes:
        print(f'{date} 無變更記錄')
        return 0

    print(f'\n{date} 變更記錄 ({len(changes)} 筆):\n')

    for c in changes:
        print(f"  [{c['change_type']}] {c['appraiser_name']}（{c['association']}）")
        if c['old_value']:
            print(f"    舊: {c['old_value']}")
        if c['new_value']:
            print(f"    新: {c['new_value']}")

    return 0

def main():
    parser = argparse.ArgumentParser(
        description='台灣不動產估價師 CRM',
        formatter_class=argparse.RawDescriptionHelpFormatter,
        epilog='''
範例:
  python main.py scrape           # 抓取並偵測變更
  python main.py scrape --no-notify  # 抓取但不發送通知
  python main.py stats            # 顯示統計
  python main.py search 張        # 搜尋姓名含「張」的估價師
  python main.py export           # 匯出 CSV
  python main.py report           # 顯示今日變更
  python main.py report --date 2026-01-07  # 顯示指定日期變更
        '''
    )

    subparsers = parser.add_subparsers(dest='command', help='指令')

    # scrape 指令
    scrape_parser = subparsers.add_parser('scrape', help='抓取並偵測變更')
    scrape_parser.add_argument('--no-notify', action='store_true', help='不發送 Telegram 通知')
    scrape_parser.add_argument('-q', '--quiet', action='store_true', help='安靜模式')

    # stats 指令
    stats_parser = subparsers.add_parser('stats', help='顯示統計')

    # search 指令
    search_parser = subparsers.add_parser('search', help='搜尋估價師')
    search_parser.add_argument('query', help='搜尋關鍵字')

    # export 指令
    export_parser = subparsers.add_parser('export', help='匯出 CSV')
    export_parser.add_argument('-o', '--output', help='輸出檔案路徑')

    # report 指令
    report_parser = subparsers.add_parser('report', help='顯示變更報告')
    report_parser.add_argument('--date', help='指定日期 (YYYY-MM-DD)')

    args = parser.parse_args()

    if not args.command:
        parser.print_help()
        return 1

    commands = {
        'scrape': cmd_scrape,
        'stats': cmd_stats,
        'search': cmd_search,
        'export': cmd_export,
        'report': cmd_report,
    }

    return commands[args.command](args)

if __name__ == '__main__':
    sys.exit(main())
