import sys
import os
from datetime import datetime, timedelta
import calendar

# Přidání adresáře src do sys.path, aby bylo možné importovat moduly
sys.path.insert(0, os.path.join(os.path.dirname(__file__)))

import database
import holidays
import data_fetcher
import rate_finder

# Global debug flag
DEBUG = False

def debug_print(*args, **kwargs):
    """Print debug messages only if debug mode is enabled."""
    if DEBUG:
        print(*args, **kwargs)

def set_debug_mode(debug):
    """Set the debug mode for this module."""
    global DEBUG
    DEBUG = debug

def get_rate_for_date_with_fallback(date_str, currency_code):
    """
    Vyhledá kurz pro zadané datum a měnu. Pokud kurz pro dané datum neexistuje,
    aplikuje pravidla pro víkendy a státní svátky podle ČNB.
    Tato funkce je upravená verze z rate_finder.py bez kontrol času.

    :param date_str: Datum ve formátu DD.MM.YYYY.
    :param currency_code: Kód měny (např. USD).
    :return: Kurz jako desetinné číslo, nebo None pokud není nalezen.
    """
    try:
        requested_date = datetime.strptime(date_str, "%d.%m.%Y")
    except ValueError:
        return None
    
    # 1. Zkusíme najít kurz pro přesné datum
    rate = database.get_rate(date_str, currency_code)
    if rate is not None:
        return rate
    
    # 2. Pokud kurz neexistuje, aplikujeme pravidla podle ČNB:
    # "Kurzy devizového trhu jsou vyhlašovány pro běžně obchodované měny, 
    # a to každý pracovní den po 14.30 s platností pro aktuální pracovní den 
    # a pro případnou následující sobotu, neděli či státní svátek"
    # 
    # To znamená:
    # - Pro víkendy a svátky hledáme kurz zpět v čase (viz níže)
    # - Pro běžné dny, které nemají kurz, hledáme kurz z posledního pracovního dne před nimi
    
    # Zkontrolujeme, zda je datum víkend nebo svátek
    if holidays.is_weekend(date_str) or holidays.is_holiday(date_str):
        # Pro víkendy a svátky hledáme kurz zpět v čase
        # podle pravidel ČNB by měl platit kurz z posledního dne před nimi,
        # který měl být vyhlášen s platností pro tento víkend/svátek.
        current_date = requested_date
        # Odečítáme dny, dokud nenajdeme den s kurzem
        # Omezení na 10 dní zpět
        for _ in range(10):
            current_date -= timedelta(days=1)
            check_date_str = current_date.strftime("%d.%m.%Y")
            rate = database.get_rate(check_date_str, currency_code)
            if rate is not None:
                # Našli jsme kurz, použijeme ho
                # (předpokládáme, že podle pravidel ČNB platí i pro následující víkend/svátek)
                return rate
        return None
    else:
        # Pro běžné dny, které nemají kurz, hledáme kurz z posledního pracovního dne před nimi
        current_date = requested_date
        # Odečítáme dny, dokud nenajdeme pracovní den s kurzem
        # Omezení na 10 dní zpět
        for _ in range(10):
            current_date -= timedelta(days=1)
            check_date_str = current_date.strftime("%d.%m.%Y")
            
            # Zkontrolujeme, zda je to pracovní den
            if not holidays.is_weekend(check_date_str) and not holidays.is_holiday(check_date_str):
                rate = database.get_rate(check_date_str, currency_code)
                if rate is not None:
                    return rate
        
        return None

def get_czech_day_name(date_str):
    """
    Vrátí český název dne v týdnu pro zadané datum.
    
    :param date_str: Datum ve formátu DD.MM.YYYY
    :return: Český název dne v týdnu
    """
    try:
        date_obj = datetime.strptime(date_str, "%d.%m.%Y")
        # Czech day names
        czech_days = ["pondělí", "úterý", "středa", "čtvrtek", "pátek", "sobota", "neděle"]
        return czech_days[date_obj.weekday()]
    except ValueError:
        return "neznámý den"

def is_holiday(date_str):
    """
    Zkontroluje, zda je zadané datum státní svátek.
    
    :param date_str: Datum ve formátu DD.MM.YYYY
    :return: True pokud je svátek, jinak False
    """
    return holidays.is_holiday(date_str)

def generate_yearly_report(year, currency_code, output_dir="data"):
    """
    Vygeneruje report kurzů pro zadaný rok a měnu.

    :param year: Rok (např. 2020).
    :param currency_code: Kód měny (např. USD).
    :param output_dir: Adresář, kam se má CSV soubor s reportem uložit.
    :return: Cesta k vytvořenému CSV souboru.
    """
    debug_print(f"Generuji report kurzů pro {currency_code} za rok {year}...")
    
    # Zkontrolujeme, zda databáze obsahuje data pro daný rok
    # Stáhneme roční data pouze pokud nejsou kompletní
    debug_print(f"Kontroluji dostupnost ročních dat pro rok {year}...")
    os.makedirs("data", exist_ok=True)
    data_fetcher.download_yearly_data(year, output_dir="data", force=False)
    
    # Vytvoříme seznam všech dní v roce
    start_date = datetime(year, 1, 1)
    end_date = datetime(year, 12, 31)
    
    # Ale nebudeme generovat report pro budoucí datumy
    today = datetime.now()
    # Pokud je požadovaný rok v budoucnosti, nepokračujeme
    if year > today.year:
        debug_print(f"Chyba: Nelze generovat report pro budoucí rok {year}.")
        return None
    
    # Pokud je požadovaný rok aktuální rok, omezíme konec na dnešní datum
    if year == today.year:
        end_date = today
    
    # Otevřeme CSV soubor pro zápis
    filename = f"report_{currency_code}_{year}.csv"
    filepath = os.path.join(output_dir, filename)
    
    try:
        with open(filepath, 'w', newline='', encoding='utf-8') as csvfile:
            # Nové pořadí sloupců: Datum, Kurz, Den v týdnu, Svátek, Poznámka
            csvfile.write("Datum,Kurz,Den v týdnu,Svátek,Poznámka\n")
            
            current_date = start_date
            while current_date <= end_date:
                date_str = current_date.strftime("%d.%m.%Y")
                
                # Získáme den v týdnu
                day_name = get_czech_day_name(date_str)
                
                # Zkontrolujeme, zda je svátek
                is_holiday_flag = is_holiday(date_str)
                holiday_text = "ano" if is_holiday_flag else "ne"
                
                # Získáme kurz pro dané datum
                rate = database.get_rate(date_str, currency_code)
                note = ""
                
                if rate is not None:
                    # Kurz byl nalezen v databázi
                    pass
                else:
                    # Kurz nebyl nalezen, zkusíme dopočítat
                    calculated_rate = get_rate_for_date_with_fallback(date_str, currency_code)
                    if calculated_rate is not None:
                        rate = calculated_rate
                        note = "Dopočítaný kurz"
                        # Pokud je kurz dopočítaný a je to svátek, přidáme informaci
                        if is_holiday_flag:
                            note += " (svátek)"
                    else:
                        note = "Kurz není k dispozici"
                
                # Zapišeme řádek do CSV
                csvfile.write(f"{date_str},{rate if rate is not None else ''},{day_name},{holiday_text},{note}\n")
                
                # Přejdeme na další den
                current_date += timedelta(days=1)
        
        debug_print(f"Report byl úspěšně uložen do: {filepath}")
        return filepath
    except IOError as e:
        debug_print(f"Chyba při zápisu do souboru: {e}")
        return None

def generate_monthly_report(year, month, currency_code, output_dir="data"):
    """
    Vygeneruje report kurzů pro zadaný měsíc, rok a měnu.

    :param year: Rok (např. 2020).
    :param month: Měsíc (1-12).
    :param currency_code: Kód měny (např. USD).
    :param output_dir: Adresář, kam se má CSV soubor s reportem uložit.
    :return: Chta k vytvořenému CSV souboru.
    """
    debug_print(f"Generuji report kurzů pro {currency_code} za {month}/{year}...")
    
    # Zkontrolujeme, zda databáze obsahuje data pro daný rok
    # Stáhneme roční data pouze pokud nejsou kompletní
    debug_print(f"Kontroluji dostupnost ročních dat pro rok {year}...")
    os.makedirs("data", exist_ok=True)
    data_fetcher.download_yearly_data(year, output_dir="data", force=False)
    
    # Vytvoříme seznam všech dní v měsíci
    start_date = datetime(year, month, 1)
    # Poslední den měsíce
    last_day = calendar.monthrange(year, month)[1]
    end_date = datetime(year, month, last_day)
    
    # Ale nebudeme generovat report pro budoucí datumy
    today = datetime.now()
    # Pokud je požadovaný měsíc v budoucnosti, nepokračujeme
    if year > today.year or (year == today.year and month > today.month):
        debug_print(f"Chyba: Nelze generovat report pro budoucí měsíc {month}/{year}.")
        return None
    
    # Pokud je požadovaný měsíc aktuální měsíc, omezíme konec na dnešní datum
    if year == today.year and month == today.month:
        end_date = today
    
    # Otevřeme CSV soubor pro zápis
    filename = f"report_{currency_code}_{year}_{month:02d}.csv"
    filepath = os.path.join(output_dir, filename)
    
    try:
        with open(filepath, 'w', newline='', encoding='utf-8') as csvfile:
            # Nové pořadí sloupců: Datum, Kurz, Den v týdnu, Svátek, Poznámka
            csvfile.write("Datum,Kurz,Den v týdnu,Svátek,Poznámka\n")
            
            current_date = start_date
            while current_date <= end_date:
                date_str = current_date.strftime("%d.%m.%Y")
                
                # Získáme den v týdnu
                day_name = get_czech_day_name(date_str)
                
                # Zkontrolujeme, zda je svátek
                is_holiday_flag = is_holiday(date_str)
                holiday_text = "ano" if is_holiday_flag else "ne"
                
                # Získáme kurz pro dané datum
                rate = database.get_rate(date_str, currency_code)
                note = ""
                
                if rate is not None:
                    # Kurz byl nalezen v databázi
                    pass
                else:
                    # Kurz nebyl nalezen, zkusíme dopočítat
                    calculated_rate = get_rate_for_date_with_fallback(date_str, currency_code)
                    if calculated_rate is not None:
                        rate = calculated_rate
                        note = "Dopočítaný kurz"
                        # Pokud je kurz dopočítaný a je to svátek, přidáme informaci
                        if is_holiday_flag:
                            note += " (svátek)"
                    else:
                        note = "Kurz není k dispozici"
                
                # Zapišeme řádek do CSV
                csvfile.write(f"{date_str},{rate if rate is not None else ''},{day_name},{holiday_text},{note}\n")
                
                # Přejdeme na další den
                current_date += timedelta(days=1)
        
        debug_print(f"Report byl úspěšně uložen do: {filepath}")
        return filepath
    except IOError as e:
        debug_print(f"Chyba při zápisu do souboru: {e}")
        return None

def generate_period_report(start_date_str, end_date_str, currency_code, output_dir="data"):
    """
    Vygeneruje report kurzů pro zadané období a měnu.

    :param start_date_str: Počáteční datum ve formátu DD.MM.YYYY.
    :param end_date_str: Koncové datum ve formátu DD.MM.YYYY.
    :param currency_code: Kód měny (např. USD).
    :param output_dir: Adresář, kam se má CSV soubor s reportem uložit.
    :return: Chta k vytvořenému CSV souboru.
    """
    debug_print(f"Generuji report kurzů pro {currency_code} za období {start_date_str} - {end_date_str}...")
    
    try:
        start_date = datetime.strptime(start_date_str, "%d.%m.%Y")
        end_date = datetime.strptime(end_date_str, "%d.%m.%Y")
    except ValueError as e:
        debug_print(f"Neplatný formát data: {e}")
        return None
    
    # Ale nebudeme generovat report pro budoucí datumy
    today = datetime.now()
    # Pokud je požadované období v budoucnosti, nepokračujeme
    if start_date.date() > today.date():
        debug_print(f"Chyba: Nelze generovat report pro období v budoucnosti (od {start_date_str}).")
        return None
    
    # Pokud je konec období v budoucnosti, omezíme ho na dnešní datum
    if end_date.date() > today.date():
        debug_print(f"Upozornění: Konec období byl omezen na dnešní datum ({today.strftime('%d.%m.%Y')}), protože zbytek je v budoucnosti.")
        end_date = today
    
    # Zkontrolujeme, zda databáze obsahuje data pro roky v rozmezí
    # Stáhneme roční data pouze pokud nejsou kompletní
    start_year = start_date.year
    end_year = end_date.year
    
    for year in range(start_year, end_year + 1):
        debug_print(f"Kontroluji dostupnost ročních dat pro rok {year}...")
        os.makedirs("data", exist_ok=True)
        data_fetcher.download_yearly_data(year, output_dir="data", force=False)
    
    # Otevřeme CSV soubor pro zápis
    filename = f"report_{currency_code}_{start_date_str.replace('.', '_')}_to_{end_date_str.replace('.', '_')}.csv"
    filepath = os.path.join(output_dir, filename)
    
    try:
        with open(filepath, 'w', newline='', encoding='utf-8') as csvfile:
            # Nové pořadí sloupců: Datum, Kurz, Den v týdnu, Svátek, Poznámka
            csvfile.write("Datum,Kurz,Den v týdnu,Svátek,Poznámka\n")
            
            current_date = start_date
            while current_date <= end_date:
                date_str = current_date.strftime("%d.%m.%Y")
                
                # Získáme den v týdnu
                day_name = get_czech_day_name(date_str)
                
                # Zkontrolujeme, zda je svátek
                is_holiday_flag = is_holiday(date_str)
                holiday_text = "ano" if is_holiday_flag else "ne"
                
                # Získáme kurz pro dané datum
                rate = database.get_rate(date_str, currency_code)
                note = ""
                
                if rate is not None:
                    # Kurz byl nalezen v databázi
                    pass
                else:
                    # Kurz nebyl nalezen, zkusíme dopočítat
                    calculated_rate = get_rate_for_date_with_fallback(date_str, currency_code)
                    if calculated_rate is not None:
                        rate = calculated_rate
                        note = "Dopočítaný kurz"
                        # Pokud je kurz dopočítaný a je to svátek, přidáme informaci
                        if is_holiday_flag:
                            note += " (svátek)"
                    else:
                        note = "Kurz není k dispozici"
                
                # Zapišeme řádek do CSV
                csvfile.write(f"{date_str},{rate if rate is not None else ''},{day_name},{holiday_text},{note}\n")
                
                # Přejdeme na další den
                current_date += timedelta(days=1)
        
        debug_print(f"Report byl úspěšně uložen do: {filepath}")
        return filepath
    except IOError as e:
        debug_print(f"Chyba při zápisu do souboru: {e}")
        return None

# Příklad použití
if __name__ == "__main__":
    # Inicializace databáze (pro případ spuštění samostatně)
    database.init_db()
    
    # Test
    # generate_yearly_report(2020, "USD")
    # generate_monthly_report(2020, 7, "USD")
    # generate_period_report("01.07.2020", "31.07.2020", "USD")