import json
from django.core.management.base import BaseCommand
from django.utils import timezone
from tongshu.models import TongshuCalendar


class Command(BaseCommand):
    help = 'Test the TongshuCalendar model with different parameters'

    def add_arguments(self, parser):
        parser.add_argument(
            '--year',
            type=int,
            help='Year to generate calendar data for (default: current year)',
        )
        parser.add_argument(
            '--month',
            type=int,
            choices=range(1, 13),
            help='Month to generate calendar data for (1-12, default: current month)',
        )
        parser.add_argument(
            '--day',
            type=int,
            help='Specific day to display details for',
        )
        parser.add_argument(
            '--days-range',
            type=str,
            help='Range of days to display (format: start-end, e.g., 1-5)',
        )
        parser.add_argument(
            '--extra-days',
            type=int,
            default=10,
            help='Number of days to include before and after the month (default: 10)',
        )
        parser.add_argument(
            '--format',
            choices=['full', 'summary', 'days-only'],
            default='summary',
            help='Output format (default: summary)',
        )
        parser.add_argument(
            '--output',
            type=str,
            help='File to write JSON output (optional)',
        )

    def handle(self, *args, **options):
        # Get parameters
        year = options.get('year')
        month = options.get('month')
        day = options.get('day')
        days_range = options.get('days_range')
        extra_days = options.get('extra_days')
        output_format = options.get('format')
        output_file = options.get('output')

        # Print input parameters
        if year is None and month is None:
            self.stdout.write(self.style.SUCCESS(f"Generating calendar for current month with {extra_days} extra days"))
        else:
            year_str = f"year {year}" if year else "current year"
            month_str = f"month {month}" if month else "current month"
            day_str = f", day {day}" if day else ""
            range_str = f", days {days_range}" if days_range else ""
            self.stdout.write(self.style.SUCCESS(f"Generating calendar for {year_str}, {month_str}{day_str}{range_str} with {extra_days} extra days"))

        # Get calendar data
        calendar_data = TongshuCalendar.get_month_data(
            year=year,
            month=month,
            extra_days=extra_days
        )
        
        # Handle days range request
        if days_range and month and year:
            try:
                start_day, end_day = map(int, days_range.split('-'))
                
                # Safety checks
                if start_day < 1 or end_day > 31 or start_day > end_day:
                    self.stdout.write(self.style.ERROR(f"Invalid days range: {days_range}"))
                    return
                
                # Unpack values from array
                year, month, month_bazi, month_element_index, days_data, prev_month, next_month = calendar_data
                    
                self.stdout.write(self.style.SUCCESS(f"\nSolar terms for days {start_day} to {end_day} in {month}/{year}:"))
                elements = ["wood", "fire", "earth", "metal", "water"]
                self.stdout.write("Date\t\tDay\tSolar Term\tIs Solar Term Day\tElement")
                self.stdout.write("----\t\t---\t----------\t----------------\t-------")
                
                for d in days_data:
                    date_str = d[0]  # First element is date string
                    if not date_str.startswith(f"{year}-{month:02d}-"):
                        continue
                        
                    day_num = int(date_str.split('-')[2])
                    if start_day <= day_num <= end_day:
                        date, day_num, is_today, bazi, lunar, lunar_formatted, jianchu, solar = d
                        solar_term_index = solar[0]
                        is_solar_term_day = solar[1] == 1
                        
                        # Get solar term name if this is a solar term day
                        term_name = ""
                        
                        self.stdout.write(f"{date}\t{day_num}\t{solar_term_index}\t\t{is_solar_term_day} {term_name}\t{elements[solar[2]] if solar[2] is not None else ''}")
                
                # Exit early for days range request
                return
            except ValueError:
                self.stdout.write(self.style.ERROR("Invalid days range format. Please use the format 'start-end' with numbers between 1 and 31."))
                return
        
        # Handle specific day request
        if day and month and year:
            target_date = f"{year}-{month:02d}-{day:02d}"
            specific_day = None
            
            # Unpack values from array
            year, month, month_bazi, month_element_index, days_data, prev_month, next_month = calendar_data
            
            for d in days_data:
                if d[0] == target_date:  # First element is the date string
                    specific_day = d
                    break
                    
            if specific_day:
                self.stdout.write(self.style.SUCCESS(f"\nDetailed info for {target_date}:"))
                date, day_num, is_today, bazi, lunar, lunar_formatted, jianchu, solar = specific_day
                
                self.stdout.write(json.dumps(specific_day, indent=2, ensure_ascii=False, default=str))
                self.stdout.write("\nDecoded values:")
                self.stdout.write(f"  Date: {date}")
                self.stdout.write(f"  Day: {day_num}")
                self.stdout.write(f"  Is today: {is_today == 1}")
                self.stdout.write(f"  Bazi: Year[{bazi[0]},{bazi[1]}] Month[{bazi[2]},{bazi[3]}] Day[{bazi[4]},{bazi[5]}]")
                self.stdout.write(f"  Lunar: {lunar[0]}/{lunar[1]}/{lunar[2]}, leap={lunar[3] == 1}")
                self.stdout.write(f"  Lunar formatted: {lunar_formatted[0]}")
                self.stdout.write(f"    Month: {lunar_formatted[1]}")
                self.stdout.write(f"    Is 3-char title: {lunar_formatted[2] == 1}")
                self.stdout.write(f"    Day: {lunar_formatted[3]}")
                self.stdout.write(f"  Jianchu: {jianchu}")
                self.stdout.write(f"  Solar term index: {solar[0]}")
                self.stdout.write(f"  Has solar term: {solar[1] == 1}")
                
                # Show element information
                elements = ["wood", "fire", "earth", "metal", "water"]
                if solar[2] is not None:
                    self.stdout.write(f"  Solar element: {elements[solar[2]]} ({solar[2]})")
                
                # Show month element
                if month_element_index is not None and 0 <= month_element_index < len(elements):
                    self.stdout.write(f"  Month element: {elements[month_element_index]} ({month_element_index})")
                
                # Exit early for specific day request
                return
        
        # Calculate the date range of the data (for debugging)
        if calendar_data[4]:  # days array, was calendar_data['days']
            first_date = calendar_data[4][0][0]  # First element is date string
            last_date = calendar_data[4][-1][0]
            self.stdout.write(self.style.SUCCESS(f"Date range: {first_date} to {last_date}"))
            
            # Check if any dates are before Feb 5th (for debugging solar terms)
            early_dates = any(
                (d[0].startswith(f"{calendar_data[0]}-01") or  # calendar_data[0] is year
                (d[0].startswith(f"{calendar_data[0]}-02") and int(d[0].split('-')[2]) < 5))
                for d in calendar_data[4]  # days array
            )
            if early_dates:
                self.stdout.write(self.style.SUCCESS(f"Note: Date range includes January/early February dates"))
            
        # Show the compact format (for demonstration)
        if calendar_data[4] and output_format == 'summary':  # calendar_data[4] is days array
            sample_day = calendar_data[4][0]
            self.stdout.write(self.style.SUCCESS(f"\nCompact format example (first day):"))
            self.stdout.write(json.dumps(sample_day, indent=2, ensure_ascii=False, default=str))
            
            # Explain the format
            self.stdout.write(self.style.SUCCESS("\nArray format explanation:"))
            self.stdout.write("Root array: [year, month, month_bazi[y_g,y_e,m_g,m_e], month_element_index, days[], prev[year,month], next[year,month]]")
            self.stdout.write("Days array: [date, day, isToday(1=true/0=false), bazi[yg,ye,mg,me,dg,de], lunar[day,month,year,isLeap], lunarFormatted[fullDate,month,isTitle3Char,day], jianchu, solar[termIndex,hasSolarTerm,elementIndex]]")

        # Process and output based on format
        if output_format == 'full':
            output_data = calendar_data
        elif output_format == 'days-only':
            output_data = calendar_data[4]  # days array
        else:  # summary
            # Unpack values from array
            year, month, month_bazi, month_element_index, days_data, prev_month, next_month = calendar_data
            
            total_days = len(days_data)
            month_info = f"Year: {year}, Month: {month}"
            bazi_info = f"Month Bazi: Year[{month_bazi[0]},{month_bazi[1]}], Month[{month_bazi[2]},{month_bazi[3]}]"
            
            # Lookup element name from index
            elements = ["wood", "fire", "earth", "metal", "water"]
            element_info = f"Month Element: {elements[month_element_index]} ({month_element_index})"
            
            self.stdout.write(self.style.SUCCESS(f"\n{month_info}"))
            self.stdout.write(self.style.SUCCESS(f"{bazi_info}"))
            self.stdout.write(self.style.SUCCESS(f"{element_info}"))
            self.stdout.write(self.style.SUCCESS(f"Total days: {total_days}"))
            
            # Sample of first 3 days
            self.stdout.write(self.style.SUCCESS("\nSample days (first 3):"))
            for i, day in enumerate(days_data[:3]):
                self.stdout.write(self.style.SUCCESS(f"\nDay {i+1}:"))
                
                # Unpack array values
                date, day_num, is_today, bazi, lunar, lunar_formatted, jianchu, solar = day
                
                self.stdout.write(f"  Date: {date}")
                self.stdout.write(f"  Day: {day_num}")
                self.stdout.write(f"  Is today: {is_today == 1}")
                
                # Display bazi in readable format
                self.stdout.write(f"  Bazi: Y[{bazi[0]},{bazi[1]}] M[{bazi[2]},{bazi[3]}] D[{bazi[4]},{bazi[5]}]")
                
                # Display lunar data
                self.stdout.write(f"  Lunar: {lunar[0]}/{lunar[1]}/{lunar[2]}, leap={lunar[3] == 1}")
                self.stdout.write(f"  Lunar formatted: {lunar_formatted[0]} (month: {lunar_formatted[1]}, day: {lunar_formatted[3]})")
                
                # Display solar term info
                solar_term_index = solar[0]
                has_solar_term = solar[1] == 1
                solar_element_index = solar[2]
                elements = ["wood", "fire", "earth", "metal", "water"]
                
                if has_solar_term:
                    self.stdout.write(f"  Solar term: {solar_term_index}")
                if solar_element_index is not None:
                    self.stdout.write(f"  Solar element: {elements[solar_element_index]} ({solar_element_index})")
            
            # Exit early for summary
            if not output_file:
                return
            
            # For file output, use full data even in summary mode
            output_data = calendar_data

        # Write to file if specified
        if output_file:
            with open(output_file, 'w', encoding='utf-8') as f:
                json.dump(output_data, f, ensure_ascii=False, indent=2, default=str)
            self.stdout.write(self.style.SUCCESS(f"\nOutput written to {output_file}"))
        elif output_format != 'summary':
            # Print JSON to stdout for non-summary formats
            self.stdout.write(json.dumps(output_data, ensure_ascii=False, indent=2, default=str)) 