"""CLI interface for panchanga using Click."""

from __future__ import annotations

import click
import sys
import json
from typing import Optional, Tuple, Dict, Any
from panchanga import (
    trunc,
    frac,
    zero360,
    modern_date_to_julian_day,
    julian_day_to_modern_date,
    julian_day_to_ahargana,
    ahargana_to_julian_day,
    get_tithi,
    get_tithi_set,
    set_sukla_krsna,
    get_naksatra_name,
    get_yoga_name,
    get_karana_name,
    get_clong,
    get_nclong,
    get_masa_num,
    get_adhimasa,
    get_saura_masa_day,
    get_saura_masa_name,
    ahargana_to_kali,
    kali_to_saka,
    saka_to_kali,
    saka_to_vikrama,
    vikrama_to_saka,
    kali_to_ahargana,
    get_vikrama_solar_year,
    get_masa_name,
    get_vikrama_saura_masa_name,
    get_jovian_year_name,
    get_jovian_year_name_south,
    get_daylight_equation,
    get_sun_rise_time,
    get_ayana_amsa,
    format_verbose_output,
    horoscope_calculation,
    format_horoscope_output,
    get_true_solar_longitude,
    get_true_lunar_longitude,
    find_samkranti,
    get_next_samkranti_info,
)

# Alias for compatibility
get_vs_saura_masa_name = get_vikrama_saura_masa_name


# Global configuration
class Config:
    def __init__(self):
        self.latitude: float = 23.2  # Default: Ujjain
        self.longitude: float = 75.8
        self.system: str = "surya"  # surya or panca
        self.quiet: bool = False
        self.json: bool = False
        self.desantara: float = 0.0  # Will be calculated from longitude


# Place coordinates database (from Perl implementation)
PLACE_COORDINATES: Dict[str, Dict[str, Any]] = {
    # Major Vedic cities
    "ujjain": {"lat": 23.2, "lon": 75.8, "name": "Ujjain"},
    "delhi": {"lat": 28.6, "lon": 77.2, "name": "Delhi"},
    "mumbai": {"lat": 19.0, "lon": 72.8, "name": "Mumbai"},
    "bangalore": {"lat": 12.9, "lon": 77.6, "name": "Bangalore"},
    "chennai": {"lat": 13.1, "lon": 80.2, "name": "Chennai"},
    "kolkata": {"lat": 22.6, "lon": 88.4, "name": "Kolkata"},
    "hyderabad": {"lat": 17.4, "lon": 78.5, "name": "Hyderabad"},
    "pune": {"lat": 18.5, "lon": 73.9, "name": "Pune"},
    "ahmedabad": {"lat": 23.0, "lon": 72.6, "name": "Ahmedabad"},
    "jaipur": {"lat": 26.9, "lon": 75.8, "name": "Jaipur"},
    "lucknow": {"lat": 26.8, "lon": 80.9, "name": "Lucknow"},
    "kanpur": {"lat": 26.4, "lon": 80.3, "name": "Kanpur"},
    "nagpur": {"lat": 21.1, "lon": 79.0, "name": "Nagpur"},
    "indore": {"lat": 22.7, "lon": 75.9, "name": "Indore"},
    "thane": {"lat": 19.2, "lon": 72.9, "name": "Thane"},
    "bhopal": {"lat": 23.3, "lon": 77.4, "name": "Bhopal"},
    "visakhapatnam": {"lat": 17.7, "lon": 83.3, "name": "Visakhapatnam"},
    "pimpri": {"lat": 18.6, "lon": 73.8, "name": "Pimpri"},
    "patna": {"lat": 25.6, "lon": 85.1, "name": "Patna"},
    "vadodara": {"lat": 22.3, "lon": 73.2, "name": "Vadodara"},
    # Religious and historical places
    "varanasi": {"lat": 25.3, "lon": 83.0, "name": "Varanasi"},
    "haridwar": {"lat": 29.9, "lon": 78.1, "name": "Haridwar"},
    "rishikesh": {"lat": 30.1, "lon": 78.3, "name": "Rishikesh"},
    "mathura": {"lat": 27.5, "lon": 77.7, "name": "Mathura"},
    "vrindavan": {"lat": 27.6, "lon": 77.7, "name": "Vrindavan"},
    "ayodhya": {"lat": 26.8, "lon": 82.2, "name": "Ayodhya"},
    "tirupati": {"lat": 13.6, "lon": 79.4, "name": "Tirupati"},
    "madurai": {"lat": 9.9, "lon": 78.1, "name": "Madurai"},
    "kanchipuram": {"lat": 12.8, "lon": 79.7, "name": "Kanchipuram"},
    "thanjavur": {"lat": 10.8, "lon": 79.1, "name": "Thanjavur"},
    "konark": {"lat": 19.9, "lon": 86.1, "name": "Konark"},
    "purushottam": {"lat": 19.8, "lon": 85.8, "name": "Purushottam"},
    "dwarka": {"lat": 22.2, "lon": 68.9, "name": "Dwarka"},
    "somnath": {"lat": 20.9, "lon": 70.4, "name": "Somnath"},
    # International cities
    "kathmandu": {"lat": 27.7, "lon": 85.3, "name": "Kathmandu"},
    "colombo": {"lat": 6.9, "lon": 79.9, "name": "Colombo"},
    "dhaka": {"lat": 23.8, "lon": 90.4, "name": "Dhaka"},
    "karachi": {"lat": 24.9, "lon": 67.0, "name": "Karachi"},
    "lahore": {"lat": 31.5, "lon": 74.4, "name": "Lahore"},
    "islamabad": {"lat": 33.7, "lon": 73.1, "name": "Islamabad"},
    "singapore": {"lat": 1.3, "lon": 103.8, "name": "Singapore"},
    "kuala_lumpur": {"lat": 3.1, "lon": 101.7, "name": "Kuala Lumpur"},
    "bangkok": {"lat": 13.8, "lon": 100.5, "name": "Bangkok"},
    "yangon": {"lat": 16.9, "lon": 96.2, "name": "Yangon"},
    # Alternative names
    "bombay": {"lat": 19.0, "lon": 72.8, "name": "Mumbai"},
    "calcutta": {"lat": 22.6, "lon": 88.4, "name": "Kolkata"},
    "madras": {"lat": 13.1, "lon": 80.2, "name": "Chennai"},
    "benares": {"lat": 25.3, "lon": 83.0, "name": "Varanasi"},
    "kashi": {"lat": 25.3, "lon": 83.0, "name": "Varanasi"},
    "puri": {"lat": 19.8, "lon": 85.8, "name": "Purushottam"},
    "jagannath": {"lat": 19.8, "lon": 85.8, "name": "Purushottam"},
}


def get_place_coordinates(place_name: str) -> Optional[Tuple[float, float, str]]:
    """Get coordinates for a place name."""
    place_name = place_name.lower()
    if place_name in PLACE_COORDINATES:
        place = PLACE_COORDINATES[place_name]
        return (place["lat"], place["lon"], place["name"])
    return None


def validate_date(year: int, month: int, day: int) -> None:
    """Validate date components."""
    if year < -4712 or year > 3000:
        raise click.BadParameter(f"Year must be between -4712 and 3000, got {year}")
    if month < 1 or month > 12:
        raise click.BadParameter(f"Month must be between 1 and 12, got {month}")
    if day < 1 or day > 31:
        raise click.BadParameter(f"Day must be between 1 and 31, got {day}")


def validate_time(hour: int, minute: int) -> None:
    """Validate time components."""
    if hour < 0 or hour > 23:
        raise click.BadParameter(f"Hour must be between 0 and 23, got {hour}")
    if minute < 0 or minute > 59:
        raise click.BadParameter(f"Minute must be between 0 and 59, got {minute}")


def validate_latitude(lat: float) -> None:
    """Validate latitude."""
    if lat < -90 or lat > 90:
        raise click.BadParameter(f"Latitude must be between -90 and 90, got {lat}")


def validate_longitude(lon: float) -> None:
    """Validate longitude."""
    if lon < -180 or lon > 180:
        raise click.BadParameter(f"Longitude must be between -180 and 180, got {lon}")


def validate_system(system: str) -> None:
    """Validate astronomical system."""
    if system not in ["surya", "suryasiddhanta", "panca", "pancasiddhantika"]:
        raise click.BadParameter(f"System must be 'surya' or 'panca', got {system}")


def validate_year_system(year_system: str) -> None:
    """Validate year system."""
    if year_system not in ["saka", "vikrama"]:
        raise click.BadParameter(f"Year system must be 'saka' or 'vikrama', got {year_system}")


def validate_paksa(paksa: str) -> None:
    """Validate paksa."""
    if paksa not in ["sukla", "krsna"]:
        raise click.BadParameter(f"Paksa must be 'sukla' or 'krsna', got {paksa}")


def validate_month(month: int) -> None:
    """Validate month number."""
    if month < 0 or month > 11:
        raise click.BadParameter(f"Month must be between 0 and 11, got {month}")


def validate_tithi(tithi: int) -> None:
    """Validate tithi day."""
    if tithi < 1 or tithi > 15:
        raise click.BadParameter(f"Tithi must be between 1 and 15, got {tithi}")


def parse_date_string(date_str: str) -> Tuple[int, int, int]:
    """Parse date string in format 'YEAR MONTH DAY'."""
    try:
        parts = date_str.strip().split()
        if len(parts) != 3:
            raise ValueError("Date must have exactly 3 parts")

        year = int(parts[0])
        month = int(parts[1])
        day = int(parts[2])

        validate_date(year, month, day)
        return (year, month, day)
    except ValueError as e:
        raise click.BadParameter(f"Invalid date format '{date_str}': {e}")


def parse_try_string(try_str: str) -> Tuple[str, int, int, str, int]:
    """Parse try string in format 'YEAR_SYSTEM YEAR MONTH PAKSA TITHI'."""
    try:
        parts = try_str.strip().split()
        if len(parts) != 5:
            raise ValueError("Try string must have exactly 5 parts")

        year_system = parts[0]
        year = int(parts[1])
        month = int(parts[2])
        paksa = parts[3]
        tithi = int(parts[4])

        validate_year_system(year_system)
        validate_date(year, 1, 1)  # Basic year validation
        validate_month(month)
        validate_paksa(paksa)
        validate_tithi(tithi)

        return (year_system, year, month, paksa, tithi)
    except ValueError as e:
        raise click.BadParameter(f"Invalid try format '{try_str}': {e}")


def parse_horoscope_string(horoscope_str: str) -> Tuple[int, int, int, int, int]:
    """Parse horoscope string in format 'YEAR MONTH DAY HOUR MINUTE'."""
    try:
        parts = horoscope_str.strip().split()
        if len(parts) != 5:
            raise ValueError("Horoscope string must have exactly 5 parts")

        year = int(parts[0])
        month = int(parts[1])
        day = int(parts[2])
        hour = int(parts[3])
        minute = int(parts[4])

        validate_date(year, month, day)
        validate_time(hour, minute)

        return (year, month, day, hour, minute)
    except ValueError as e:
        raise click.BadParameter(f"Invalid horoscope format '{horoscope_str}': {e}")


def calculate_desantara(longitude: float) -> float:
    """Calculate desantara correction from longitude."""
    ujjaini_lon = 75.8  # Ujjain longitude
    return (longitude - ujjaini_lon) / 360


def initialize_calculations(config: Config) -> None:
    """Initialize calculation constants."""
    # For now, we'll use simplified initialization
    # In a full implementation, this would call the astronomy initialization functions
    pass

    # Calculate desantara from longitude
    config.desantara = calculate_desantara(config.longitude)


def get_weekday_name(julian_day: float) -> str:
    """Get weekday name from Julian day."""
    weekdays = [
        "Sunday",
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday",
    ]
    day_of_week = int(julian_day + 1.5) % 7
    return weekdays[day_of_week]


def perform_calculations(year: int, month: int, day: int, config: Config) -> Dict[str, Any]:
    """Perform all calculations for a given date."""
    # Convert to Julian day and ahargana
    julian_day = modern_date_to_julian_day(year, month, day)
    ahargana_base = julian_day_to_ahargana(julian_day)  # Keep base ahargana for ayanamsa
    # Round Julian Day to nearest integer like Perl does
    julian_day = int(julian_day + 0.5)
    # Round ahargana to nearest integer like Perl does (for display)
    ahargana = int(ahargana_base + 0.5)

    # Get weekday
    weekday_name = get_weekday_name(julian_day)

    # Calculate ayanamsa using BASE ahargana (before rounding, like Perl)
    ayanadeg, ayanamin = get_ayana_amsa(ahargana_base)

    # Use ahar for calculations (like Perl does) - keep ahargana as int for display
    ahar = ahargana_base

    # Adjust for local time (6 AM)
    ahar = ahar + 0.25

    # Apply desantara correction
    ahar = ahar - config.desantara

    # Calculate sunrise time
    eqtime = get_daylight_equation(year, config.latitude, ahar)
    sunrise_hour, sunrise_minute = get_sun_rise_time(eqtime)
    ahar = ahar - eqtime

    # Calculate lunar and solar longitudes
    tslong = get_true_solar_longitude(ahar)
    tllong = get_true_lunar_longitude(ahar)

    # Calculate tithi and related
    tithi = get_tithi(tllong, tslong)
    tithi_day, ftithi = get_tithi_set(tithi)
    tithi_day_adj, sukla_krsna, paksa = set_sukla_krsna(tithi_day)

    # Calculate naksatra, yoga, karana
    naksatra = get_naksatra_name(zero360(tllong))
    yoga = get_yoga_name(tslong, tllong)
    karana = get_karana_name(tithi)

    # Calculate solar month
    saura_masa_num, saura_masa_day = get_saura_masa_day(ahar)
    saura_masa = get_saura_masa_name(saura_masa_num)

    # Calculate samkranti information
    # Find previous samkranti (the one that occurred before current date)
    # We need to look backwards to find the samkranti that started the current solar month
    base_ahar = trunc(ahar)
    samkranti_ahar = None
    samkranti_year = samkranti_month = samkranti_day = 1  # Initialize to 1 like Perl
    samkranti_hour = samkranti_minute = 0

    # First check if there's a samkranti on the current day (like Perl does)
    tslong_today = get_true_solar_longitude(base_ahar - config.desantara)
    tslong_tomorrow = get_true_solar_longitude(base_ahar - config.desantara + 1)
    tslong_today = tslong_today - int(tslong_today / 30) * 30
    tslong_tomorrow = tslong_tomorrow - int(tslong_tomorrow / 30) * 30

    if (25 < tslong_today) and (tslong_tomorrow < 5):
        # Found samkranti on current day
        samkranti_ahar = find_samkranti(base_ahar, base_ahar + 1)
        samkranti_ahar = samkranti_ahar + config.desantara
        samkranti_jd = ahargana_to_julian_day(trunc(samkranti_ahar) + 0.5)
        samkranti_year, samkranti_month, samkranti_day = julian_day_to_modern_date(samkranti_jd)
        samkranti_hour = trunc(frac(samkranti_ahar) * 24)
        samkranti_minute = trunc(60 * frac(frac(samkranti_ahar) * 24))
    else:
        # Look backward for previous samkranti
        for k in range(
            1, 35
        ):  # Start from 1, not 0 (we already checked current day), go up to 34 days back to cover full solar month
            candidate_ahar = base_ahar - k
            # Check if this day contains a samkranti window
            tslong_today = get_true_solar_longitude(candidate_ahar - config.desantara)
            tslong_tomorrow = get_true_solar_longitude(candidate_ahar - config.desantara + 1)
            tslong_today = tslong_today - int(tslong_today / 30) * 30
            tslong_tomorrow = tslong_tomorrow - int(tslong_tomorrow / 30) * 30

            if (25 < tslong_today) and (tslong_tomorrow < 5):
                # Found samkranti window
                samkranti_ahar = find_samkranti(candidate_ahar, candidate_ahar + 1)
                samkranti_ahar = samkranti_ahar + config.desantara
                samkranti_jd = ahargana_to_julian_day(trunc(samkranti_ahar) + 0.5)
                samkranti_year, samkranti_month, samkranti_day = julian_day_to_modern_date(
                    samkranti_jd
                )
                samkranti_hour = trunc(frac(samkranti_ahar) * 24)
                samkranti_minute = trunc(60 * frac(frac(samkranti_ahar) * 24))
                break

    # Get next samkranti info
    (
        next_samkranti_days,
        next_samkranti_hour,
        next_samkranti_minute,
        next_samkranti_ahar,
    ) = get_next_samkranti_info(ahargana, config.desantara)
    if next_samkranti_days is not None:
        next_samkranti_jd = ahargana_to_julian_day(trunc(next_samkranti_ahar) + 0.5)
        next_samkranti_year, next_samkranti_month, next_samkranti_day = julian_day_to_modern_date(
            next_samkranti_jd
        )
    else:
        next_samkranti_year = next_samkranti_month = next_samkranti_day = None

    # Calculate conjunction longitudes for masa calculation
    clong = get_clong(ahargana, tithi)
    nclong = get_nclong(ahargana, tithi)

    # Calculate masa_num (lunar month number) using conjunction longitude
    masa_num = get_masa_num(tslong, clong)

    # Calculate adhimasa (leap month) prefix
    adhimasa = get_adhimasa(clong, nclong)

    # Calculate Kali year with masa adjustment (simplified)
    kali_ahargana = ahar + (4 - masa_num) * 30
    kali_year = ahargana_to_kali(kali_ahargana)
    saka_year = kali_to_saka(kali_year)
    vikrama_year = saka_to_vikrama(saka_year)

    # Calculate VS solar year
    vikrama_solar_year = get_vikrama_solar_year(vikrama_year, saura_masa_num)
    vikram_saura_masa = get_vs_saura_masa_name(saura_masa_num)

    # Get masa name with adhimasa prefix
    masa = adhimasa + get_masa_name(masa_num)

    # Calculate Jovian year information
    jovian_north = get_jovian_year_name(kali_year)
    jovian_south = get_jovian_year_name_south(kali_year)

    return {
        "year": year,
        "month": month,
        "day": day,
        "weekday_name": weekday_name,
        "julian_day": julian_day,
        "ahargana": ahargana,
        "sunrise_hour": sunrise_hour,
        "sunrise_minute": sunrise_minute,
        "ayanadeg": ayanadeg,
        "ayanamin": ayanamin,
        "saka_year": saka_year,
        "vikrama_year": vikrama_year,
        "kali_year": kali_year,
        "vikrama_solar_year": vikrama_solar_year,
        "adhimasa": "",  # Placeholder
        "masa": masa,
        "sukla_krsna": paksa,
        "tithi_day": tithi_day_adj,
        "ftithi": ftithi,
        "saura_masa": saura_masa,
        "saura_masa_day": saura_masa_day,
        "samkranti_year": samkranti_year,
        "samkranti_month": samkranti_month,
        "samkranti_day": samkranti_day,
        "samkranti_hour": samkranti_hour,
        "samkranti_minute": samkranti_minute,
        "vikram_saura_masa": vikram_saura_masa,
        "naksatra": naksatra,
        "karana": karana,
        "yoga": yoga,
        "tslong": tslong,
        "tllong": tllong,
        "jovian_north": jovian_north,
        "jovian_south": jovian_south,
        "next_samkranti_year": next_samkranti_year,
        "next_samkranti_month": next_samkranti_month,
        "next_samkranti_day": next_samkranti_day,
        "next_samkranti_hour": next_samkranti_hour,
        "next_samkranti_minute": next_samkranti_minute,
    }


@click.group()
@click.option("--latitude", "-lat", type=float, help="Set latitude (-80 to 80, default: 23.2)")
@click.option("--longitude", "-lon", type=float, help="Set longitude (-180 to 180, default: 75.8)")
@click.option("--place", "-p", type=str, help="Set location by place name")
@click.option(
    "--system",
    "-s",
    type=str,
    default="surya",
    help="Astronomical system: surya|panca (default: surya)",
)
@click.option("--quiet", "-q", is_flag=True, help="Quiet mode (minimal output)")
@click.option("--json", "-j", is_flag=True, help="JSON output format")
@click.pass_context
def cli(ctx, latitude, longitude, place, system, quiet, json):
    """Panchanga - Traditional Vedic Calendar (CLI Version)"""
    # Initialize config
    config = Config()
    config.quiet = quiet
    config.json = json

    # Handle place name
    if place:
        coords = get_place_coordinates(place)
        if coords:
            lat, lon, name = coords
            config.latitude = lat
            config.longitude = lon
            if not quiet:
                click.echo(f"Using coordinates for {name}: {lat}°N, {lon}°E", err=True)
        else:
            click.echo(
                f"Error: Unknown place '{place}'. Use 'panchanga places' to see available places.",
                err=True,
            )
            sys.exit(1)

    # Handle explicit coordinates
    if latitude is not None:
        validate_latitude(latitude)
        config.latitude = latitude
    if longitude is not None:
        validate_longitude(longitude)
        config.longitude = longitude

    # Handle system
    validate_system(system)
    if system in ["surya", "suryasiddhanta"]:
        config.system = "surya"
    elif system in ["panca", "pancasiddhantika"]:
        config.system = "panca"

    # Store config in context
    ctx.obj = config


@cli.command()
@click.argument("date_str", type=str)
@click.pass_context
def list_cmd(ctx, date_str):
    """Convert modern date to Vedic calendar (List mode)"""
    config = ctx.obj
    initialize_calculations(config)

    try:
        year, month, day = parse_date_string(date_str)

        # Perform calculations for 10 consecutive days
        from datetime import datetime, timedelta

        start_date = datetime(year, month, day)

        for i in range(10):
            current_date = start_date + timedelta(days=i)
            current_year = current_date.year
            current_month = current_date.month
            current_day = current_date.day

            results = perform_calculations(current_year, current_month, current_day, config)

            # Format output
            if config.json:
                # Create simplified output matching Perl format
                simple_result = {
                    "year": current_year,
                    "month": current_month,
                    "day": current_day,
                    "weekday": results["weekday_name"],
                    "saka_year": results["saka_year"],
                    "vikrama_year": results["vikrama_year"],
                    "masa": results["masa"],
                    "paksa": results["sukla_krsna"],
                    "tithi": results["tithi_day"],
                    "naksatra": results["naksatra"],
                }
                click.echo(json.dumps(simple_result, indent=2))
            else:
                click.echo(
                    f"{current_year:4d} {current_month:2d} {current_day:2d} {results['weekday_name'][:3]}"
                    f"|Saka {results['saka_year']:4d}|V.S.{results['vikrama_year']:4d}        "
                    f"{results['masa']:6s}  {results['sukla_krsna']:5s} {results['tithi_day']:2d} "
                    f"{results['naksatra']}"
                )
                click.echo(
                    "==============================================================================="
                )

    except click.BadParameter as e:
        click.echo(f"Error: {e}", err=True)
        sys.exit(1)


@cli.command()
@click.argument("date_str", type=str)
@click.pass_context
def verbose(ctx, date_str):
    """Get detailed information for a date (Verbose mode)"""
    config = ctx.obj
    initialize_calculations(config)

    try:
        year, month, day = parse_date_string(date_str)
        results = perform_calculations(year, month, day, config)

        if config.json:
            click.echo(json.dumps(results, indent=2))
        else:
            # Format verbose output
            verbose_output = format_verbose_output(
                results["year"],
                results["month"],
                results["day"],
                results["weekday_name"],
                results["julian_day"],
                results["ahargana"],
                config.latitude,
                config.longitude,
                results["sunrise_hour"],
                results["sunrise_minute"],
                results["ayanadeg"],
                results["ayanamin"],
                results["saka_year"],
                results["vikrama_year"],
                results["kali_year"],
                results["adhimasa"],
                results["masa"],
                results["sukla_krsna"],
                results["tithi_day"],
                results["ftithi"],
                results["saura_masa"],
                results["saura_masa_day"],
                results["samkranti_year"],
                results["samkranti_month"],
                results["samkranti_day"],
                results["samkranti_hour"],
                results["samkranti_minute"],
                results["vikrama_solar_year"],
                results["vikram_saura_masa"],
                results["naksatra"],
                results["karana"],
                results["yoga"],
                results["tslong"],
                results["tllong"],
                results["jovian_north"],
                results["jovian_south"],
                results["next_samkranti_year"],
                results["next_samkranti_month"],
                results["next_samkranti_day"],
                results["next_samkranti_hour"],
                results["next_samkranti_minute"],
            )
            click.echo(verbose_output)

    except click.BadParameter as e:
        click.echo(f"Error: {e}", err=True)
        sys.exit(1)


@cli.command()
@click.argument("year", type=int)
@click.argument("month", type=int)
@click.argument("tithi", type=int)
@click.option(
    "--paksa",
    type=click.Choice(["sukla", "krsna", "S", "K"]),
    default="sukla",
    help="Paksa: sukla or krsna (default: sukla)",
)
@click.option(
    "--year-system",
    type=click.Choice(["saka", "vikrama", "S", "V"]),
    default="saka",
    help="Year system: saka or vikrama (default: saka)",
)
@click.pass_context
def try_cmd(ctx, year, month, tithi, paksa, year_system):
    """Convert Vedic date to modern date (Try mode)

    Examples:
        panchanga try 1945 0 1 --paksa sukla --year-system saka
        panchanga try 2080 0 15 --paksa krsna --year-system vikrama
        panchanga try 1945 0 1  # defaults to Saka year, Sukla paksa
    """
    config = ctx.obj
    initialize_calculations(config)

    try:
        # Normalize paksa input
        if paksa.upper() == "S":
            paksa = "sukla"
        elif paksa.upper() == "K":
            paksa = "krsna"

        # Normalize year system input
        if year_system.upper() == "S":
            year_system = "saka"
        elif year_system.upper() == "V":
            year_system = "vikrama"

        # Validate inputs
        validate_month(month)
        validate_tithi(tithi)
        validate_paksa(paksa)
        validate_year_system(year_system)

        # Convert to Kali year
        if year_system == "saka":
            kali_year = saka_to_kali(year)
            display_saka_year = year
            display_vikrama_year = saka_to_vikrama(year)
        else:  # vikrama
            saka_year = vikrama_to_saka(year)
            kali_year = saka_to_kali(saka_year)
            display_saka_year = saka_year
            display_vikrama_year = year

        # Store original tithi for display
        original_tithi = tithi

        # Handle paksa (add 15 to tithi if krsna paksa) for calculation only
        if paksa.lower() == "krsna":
            tithi = tithi + 15

        # Calculate ahargana using proper conversion
        ahargana = kali_to_ahargana(kali_year, month, tithi)

        # Convert to Julian day
        julian_day = ahargana_to_julian_day(ahargana)
        julian_day = julian_day + 0.5  # Add 0.5 like Perl does

        # Convert to modern date
        modern_year, modern_month, modern_day = julian_day_to_modern_date(julian_day)

        # Get weekday
        weekday_name = get_weekday_name(julian_day)

        if config.json:
            # Get masa name for display
            masa_name = get_masa_name(month)

            # Convert abbreviated paksa to full form
            full_paksa = "Suklapaksa" if paksa.lower() == "sukla" else "Krsnapaksa"

            result = {
                "saka_year": display_saka_year,
                "vikrama_year": display_vikrama_year,
                "masa": masa_name,
                "paksa": full_paksa,
                "tithi": original_tithi,
                "modern_year": modern_year,
                "modern_month": modern_month,
                "modern_day": modern_day,
                "weekday": weekday_name,
            }
            click.echo(json.dumps(result, indent=2))
        else:
            # Convert abbreviated paksa to full form
            full_paksa = "Suklapaksa" if paksa.lower() == "sukla" else "Krsnapaksa"
            click.echo("=" * 79)
            click.echo(
                f"Saka {display_saka_year} Vikrama {display_vikrama_year} | {get_masa_name(month)} {full_paksa} {original_tithi:3d}  "
                f"| AD{modern_year:5d} {modern_month:2d} {modern_day:2d} {weekday_name}"
            )
            click.echo("=" * 79)

    except click.BadParameter as e:
        click.echo(f"Error: {e}", err=True)
        sys.exit(1)


@cli.command()
@click.argument("horoscope_str", type=str)
@click.pass_context
def horoscope(ctx, horoscope_str):
    """Calculate horoscope for a specific date and time"""
    config = ctx.obj
    initialize_calculations(config)

    try:
        year, month, day, hour, minute = parse_horoscope_string(horoscope_str)

        # Perform horoscope calculation
        horoscope_data = horoscope_calculation(
            year, month, day, hour, minute, config.latitude, config.longitude
        )

        if config.json:
            horoscope_json = {
                "date": f"{year:4d}{month:3d}{day:3d}",
                "time": f"{hour:2d}h{minute:2d}m",
                "latitude": config.latitude,
                "longitude": config.longitude,
                "lagna": horoscope_data["lagna"],
                "ascendant": horoscope_data["ascendant"],
                "solar_longitude": horoscope_data["true_solar_long"],
                "solar_declination": horoscope_data["solar_declination"],
                "solar_right_ascension": horoscope_data["solar_right_ascension"],
                "hour_angle": horoscope_data["hrasc"],
                "julian_day": horoscope_data["julian_day"],
                "ahargana": horoscope_data["ahargana"],
            }
            click.echo(json.dumps(horoscope_json, indent=2))
        else:
            # Use the formatted output from horoscope module
            output = format_horoscope_output(horoscope_data)
            click.echo(output)

    except click.BadParameter as e:
        click.echo(f"Error: {e}", err=True)
        sys.exit(1)


@cli.command()
@click.pass_context
def places(ctx):
    """List available place names"""

    click.echo("Available places:\n")

    click.echo("Major Vedic Cities:")
    major_cities = [
        "ujjain",
        "delhi",
        "mumbai",
        "bangalore",
        "chennai",
        "kolkata",
        "hyderabad",
        "pune",
        "ahmedabad",
        "jaipur",
        "lucknow",
        "kanpur",
        "nagpur",
        "indore",
        "thane",
        "bhopal",
        "visakhapatnam",
        "pimpri",
        "patna",
        "vadodara",
    ]
    for city in major_cities:
        if city in PLACE_COORDINATES:
            place = PLACE_COORDINATES[city]
            click.echo(f"  {city:<15s} ({place['name']}) - {place['lat']}°N, {place['lon']}°E")

    click.echo("\nReligious and Historical Places:")
    religious_places = [
        "varanasi",
        "haridwar",
        "rishikesh",
        "mathura",
        "vrindavan",
        "ayodhya",
        "tirupati",
        "madurai",
        "kanchipuram",
        "thanjavur",
        "konark",
        "purushottam",
        "dwarka",
        "somnath",
    ]
    for place_name in religious_places:
        if place_name in PLACE_COORDINATES:
            place = PLACE_COORDINATES[place_name]
            click.echo(
                f"  {place_name:<15s} ({place['name']}) - {place['lat']}°N, {place['lon']}°E"
            )

    click.echo("\nInternational Cities:")
    intl_cities = [
        "kathmandu",
        "colombo",
        "dhaka",
        "karachi",
        "lahore",
        "islamabad",
        "singapore",
        "kuala_lumpur",
        "bangkok",
        "yangon",
    ]
    for city in intl_cities:
        if city in PLACE_COORDINATES:
            place = PLACE_COORDINATES[city]
            click.echo(f"  {city:<15s} ({place['name']}) - {place['lat']}°N, {place['lon']}°E")

    click.echo("\nAlternative Names:")
    alt_names = [
        "bombay",
        "calcutta",
        "madras",
        "benares",
        "kashi",
        "puri",
        "jagannath",
    ]
    for alt in alt_names:
        if alt in PLACE_COORDINATES:
            place = PLACE_COORDINATES[alt]
            click.echo(f"  {alt:<15s} ({place['name']}) - {place['lat']}°N, {place['lon']}°E")

    click.echo("\nNote: Use --place 'place_name' or --latitude X --longitude Y")


@cli.command()
@click.pass_context
def settings(ctx):
    """Show current settings"""
    config = ctx.obj

    if config.json:
        settings_data = {
            "latitude": config.latitude,
            "longitude": config.longitude,
            "system": config.system,
            "desantara": config.desantara,
        }
        click.echo(json.dumps(settings_data, indent=2))
    else:
        click.echo("Current settings:")
        click.echo(f"  Latitude: {config.latitude}°N")
        click.echo(f"  Longitude: {config.longitude}°E")
        click.echo(f"  System: {config.system}")
        click.echo(f"  Desantara: {config.desantara:.6f}")


@cli.command()
@click.pass_context
def version(ctx):
    """Show version information"""
    click.echo("Panchanga Python Version 0.1.0")
    click.echo("Based on Suryasiddhanta (AD 1000 ca)")
    click.echo("Port of pancanga.pl by M. YANO and M. FUSHIMI")
    click.echo("Port by Ayush Jha")


if __name__ == "__main__":
    cli()
