#!/usr/bin/env python3
"""
Improved Excel creation script that processes templates in memory
to prevent external link issues in Excel.
"""
import json
import os
import datetime
from pathlib import Path
from dateutil.relativedelta import relativedelta
import openpyxl
from openpyxl.utils import get_column_letter


def create_excel_from_template():
    """
    Create an Excel file from template with all placeholders replaced in memory
    before saving to prevent external link issues.
    """
    # Define paths
    script_dir = os.path.dirname(os.path.abspath(__file__))
    config_path = os.path.join(script_dir, 'config.json')
    # Check for both possible template names
    template_dir = os.path.join(script_dir, 'template')

    # Try to find the template with either naming convention
    possible_templates = [
        'Footprints AI for {store_name} - Retail Media Business Case Calculations.xlsx',
        'Footprints AI for store_name - Retail Media Business Case Calculations.xlsx'
    ]

    template_path = None
    for template_name in possible_templates:
        full_path = os.path.join(template_dir, template_name)
        if os.path.exists(full_path):
            template_path = full_path
            print(f"Found template: {template_name}")
            break

    if not template_path:
        print(f"Error: No template found in {template_dir}")
        return False

    output_dir = os.path.join(script_dir, 'output')

    # Ensure output directory exists
    os.makedirs(output_dir, exist_ok=True)

    # Read config.json
    try:
        with open(config_path, 'r') as f:
            config = json.load(f)
            user_data = config.get('user_data', {})
            store_name = user_data.get('store_name', 'Your Store')
            starting_date = user_data.get('starting_date', '')
            duration = user_data.get('duration', 36)

            if not store_name:
                store_name = "Your Store"

            print(f"Processing for store: {store_name}")

            # Calculate years array
            years = calculate_years(starting_date, duration)
            calculated_years = years  # For sheet visibility later
            print(f"Years in the period: {years}")
    except Exception as e:
        print(f"Error reading config file: {e}")
        return False

    # Determine year range for filename
    year_range = ""
    if years and len(years) > 0:
        if len(years) == 1:
            year_range = f"{years[0]}"
        else:
            year_range = f"{years[0]}-{years[-1]}"
    else:
        year_range = f"{datetime.datetime.now().year}"

    # Create output filename
    output_filename = f"Footprints AI for {store_name} - Retail Media Business Case Calculations {year_range}.xlsx"
    output_path = os.path.join(output_dir, output_filename)

    try:
        # STAGE 1: Load template and replace all placeholders in memory
        print("Loading template in memory...")
        wb = openpyxl.load_workbook(template_path, data_only=False)

        # Build mapping of placeholder patterns to actual values
        # Support both {store_name} and store_name formats
        placeholder_patterns = [
            ('{store_name}', store_name),
            ('store_name', store_name)  # New format without curly braces
        ]

        # STAGE 2: Replace placeholders in sheet names first
        print("Replacing placeholders in sheet names...")
        sheet_name_mappings = {}

        for sheet in wb.worksheets:
            old_title = sheet.title
            new_title = old_title

            # Replace all placeholder patterns in sheet name
            for placeholder, replacement in placeholder_patterns:
                if placeholder in new_title:
                    new_title = new_title.replace(placeholder, replacement)
                    print(f"  Sheet name: '{old_title}' -> '{new_title}'")

            if old_title != new_title:
                # Store the mapping for formula updates
                sheet_name_mappings[old_title] = new_title
                # Also store with quotes for formula references
                sheet_name_mappings[f"'{old_title}'"] = f"'{new_title}'"

        # STAGE 3: Update all formulas and cell values BEFORE renaming sheets
        print("Updating formulas and cell values...")
        total_replacements = 0

        for sheet in wb.worksheets:
            sheet_name = sheet.title
            replacements_in_sheet = 0

            # Skip Variables sheet to avoid issues
            if 'Variables' in sheet_name:
                continue

            for row in sheet.iter_rows():
                for cell in row:
                    # Handle formulas
                    if cell.data_type == 'f' and cell.value:
                        original_formula = str(cell.value)
                        new_formula = original_formula

                        # First replace sheet references
                        for old_ref, new_ref in sheet_name_mappings.items():
                            if old_ref in new_formula:
                                new_formula = new_formula.replace(old_ref, new_ref)

                        # Then replace any remaining placeholders
                        for placeholder, replacement in placeholder_patterns:
                            if placeholder in new_formula:
                                new_formula = new_formula.replace(placeholder, replacement)

                        if new_formula != original_formula:
                            cell.value = new_formula
                            replacements_in_sheet += 1

                    # Handle text values
                    elif cell.value and isinstance(cell.value, str):
                        original_value = str(cell.value)
                        new_value = original_value

                        for placeholder, replacement in placeholder_patterns:
                            if placeholder in new_value:
                                new_value = new_value.replace(placeholder, replacement)

                        if new_value != original_value:
                            cell.value = new_value
                            replacements_in_sheet += 1

            if replacements_in_sheet > 0:
                print(f"  {sheet_name}: {replacements_in_sheet} replacements")
                total_replacements += replacements_in_sheet

        print(f"Total replacements: {total_replacements}")

        # STAGE 4: Now rename the sheets (after formulas are updated)
        print("Renaming sheets...")
        for sheet in wb.worksheets:
            old_title = sheet.title
            new_title = old_title

            for placeholder, replacement in placeholder_patterns:
                if placeholder in new_title:
                    new_title = new_title.replace(placeholder, replacement)

            if old_title != new_title:
                sheet.title = new_title
                print(f"  Renamed: '{old_title}' -> '{new_title}'")

                # Check if this is a forecast sheet and hide if needed
                if "Forecast" in new_title:
                    try:
                        # Extract year from sheet name
                        sheet_year = int(new_title.split()[0])
                        if sheet_year not in calculated_years:
                            sheet.sheet_state = 'hidden'
                            print(f"  Hidden sheet '{new_title}' (year {sheet_year} not in range)")
                    except (ValueError, IndexError):
                        pass

        # STAGE 5: Update Variables sheet with config values
        print("Updating Variables sheet...")
        if 'Variables' in wb.sheetnames:
            update_variables_sheet(wb['Variables'], user_data)

        # STAGE 6: Save the fully processed workbook
        print(f"Saving to: {output_path}")
        wb.save(output_path)

        print(f"✓ Excel file created successfully: {output_filename}")
        return True

    except Exception as e:
        print(f"Error creating Excel file: {e}")
        import traceback
        traceback.print_exc()
        return False


def update_variables_sheet(sheet, user_data):
    """
    Update the Variables sheet with values from config.json
    """
    # Map config variables to Excel cells
    cell_mappings = {
        'B2': user_data.get('store_name', ''),
        'B31': user_data.get('starting_date', ''),
        'B32': user_data.get('duration', 36),
        'B37': user_data.get('open_days_per_month', 0),

        # Convenience store type
        'H37': user_data.get('convenience_store_type', {}).get('stores_number', 0),
        'C37': user_data.get('convenience_store_type', {}).get('monthly_transactions', 0),
        'I37': 1 if user_data.get('convenience_store_type', {}).get('has_digital_screens', False) else 0,
        'J37': user_data.get('convenience_store_type', {}).get('screen_count', 0),
        'K37': user_data.get('convenience_store_type', {}).get('screen_percentage', 0),
        'M37': 1 if user_data.get('convenience_store_type', {}).get('has_in_store_radio', False) else 0,
        'N37': user_data.get('convenience_store_type', {}).get('radio_percentage', 0),

        # Minimarket store type
        'H38': user_data.get('minimarket_store_type', {}).get('stores_number', 0),
        'C38': user_data.get('minimarket_store_type', {}).get('monthly_transactions', 0),
        'I38': 1 if user_data.get('minimarket_store_type', {}).get('has_digital_screens', False) else 0,
        'J38': user_data.get('minimarket_store_type', {}).get('screen_count', 0),
        'K38': user_data.get('minimarket_store_type', {}).get('screen_percentage', 0),
        'M38': 1 if user_data.get('minimarket_store_type', {}).get('has_in_store_radio', False) else 0,
        'N38': user_data.get('minimarket_store_type', {}).get('radio_percentage', 0),

        # Supermarket store type
        'H39': user_data.get('supermarket_store_type', {}).get('stores_number', 0),
        'C39': user_data.get('supermarket_store_type', {}).get('monthly_transactions', 0),
        'I39': 1 if user_data.get('supermarket_store_type', {}).get('has_digital_screens', False) else 0,
        'J39': user_data.get('supermarket_store_type', {}).get('screen_count', 0),
        'K39': user_data.get('supermarket_store_type', {}).get('screen_percentage', 0),
        'M39': 1 if user_data.get('supermarket_store_type', {}).get('has_in_store_radio', False) else 0,
        'N39': user_data.get('supermarket_store_type', {}).get('radio_percentage', 0),

        # Hypermarket store type
        'H40': user_data.get('hypermarket_store_type', {}).get('stores_number', 0),
        'C40': user_data.get('hypermarket_store_type', {}).get('monthly_transactions', 0),
        'I40': 1 if user_data.get('hypermarket_store_type', {}).get('has_digital_screens', False) else 0,
        'J40': user_data.get('hypermarket_store_type', {}).get('screen_count', 0),
        'K40': user_data.get('hypermarket_store_type', {}).get('screen_percentage', 0),
        'M40': 1 if user_data.get('hypermarket_store_type', {}).get('has_in_store_radio', False) else 0,
        'N40': user_data.get('hypermarket_store_type', {}).get('radio_percentage', 0),

        # On-site channels
        'B43': user_data.get('website_visitors', 0),
        'B44': user_data.get('app_users', 0),
        'B45': user_data.get('loyalty_users', 0),

        # Off-site channels
        'B49': user_data.get('facebook_followers', 0),
        'B50': user_data.get('instagram_followers', 0),
        'B51': user_data.get('google_views', 0),
        'B52': user_data.get('email_subscribers', 0),
        'B53': user_data.get('sms_users', 0),
        'B54': user_data.get('whatsapp_contacts', 0)
    }

    # Update the cells
    for cell_ref, value in cell_mappings.items():
        try:
            sheet[cell_ref].value = value
            print(f"  Updated {cell_ref} = {value}")
        except Exception as e:
            print(f"  Warning: Could not update {cell_ref}: {e}")


def calculate_years(starting_date, duration):
    """
    Calculate an array of years that appear in the period.
    """
    default_years = [datetime.datetime.now().year]

    if not starting_date:
        return default_years

    try:
        # Parse date - support multiple formats
        if '/' in str(starting_date):
            day, month, year = map(int, str(starting_date).split('/'))
        elif '.' in str(starting_date):
            day, month, year = map(int, str(starting_date).split('.'))
        elif '-' in str(starting_date):
            # ISO format (yyyy-mm-dd)
            date_parts = str(starting_date).split('-')
            if len(date_parts) == 3:
                year, month, day = map(int, date_parts)
            else:
                return default_years
        else:
            return default_years

        # Create datetime object
        start_date = datetime.datetime(year, month, day)

        # Calculate end date
        end_date = start_date + relativedelta(months=duration-1)

        # Create set of years
        years_set = set()
        years_set.add(start_date.year)
        years_set.add(end_date.year)

        # Add any years in between
        for y in range(start_date.year + 1, end_date.year):
            years_set.add(y)

        return sorted(list(years_set))

    except Exception as e:
        print(f"Error calculating years: {e}")
        return default_years


if __name__ == "__main__":
    create_excel_from_template()