using System;
using UnityEngine;

namespace Jovian.Calendar {
    /// <summary>
    /// ScriptableObject defining the rules of an in-game calendar: day length, hours, minutes,
    /// month structure, month names, week length, and starting date. Create via
    /// Assets > Create > Jovian > Calendar > Calendar Settings.
    /// </summary>
    [CreateAssetMenu(fileName = "CalendarSettings", menuName = "Jovian/Calendar/Calendar Settings")]
    public class CalendarSettings : ScriptableObject {
        /// <summary>How many real-time seconds one full 0 to 1 float cycle represents.</summary>
        public float secondsPerFullDay;

        /// <summary>How many in-world hours per day (e.g. 24, or 16 for a shorter day).</summary>
        public int hoursPerDay;

        /// <summary>How many in-world minutes per hour (e.g. 60).</summary>
        public int minutesPerHour;

        /// <summary>
        /// Days in each month, in order. Length of this array defines months per year.
        /// E.g. { 30, 28, 31 } = 3 months with different lengths.
        /// </summary>
        public int[] daysPerMonth;

        /// <summary>
        /// Custom month names. Must match daysPerMonth.Length.
        /// </summary>
        public string[] monthNames;

        /// <summary>Optional: days per week for week-tracking. 0 to disable.</summary>
        public int daysPerWeek;

        // --- Starting date ---
        public int startYear;
        public int startMonth; // 0-indexed
        public int startDay; // 0-indexed
        public int startHour;
        public int startMinute;

        /// <summary>Number of months in a year, derived from daysPerMonth array length.</summary>
        public int MonthsPerYear => daysPerMonth?.Length ?? 0;

        /// <summary>Total days in one full year.</summary>
        public int TotalDaysInYear {
            get {
                var total = 0;
                if(daysPerMonth == null) {
                    return 0;
                }
                foreach(var t in daysPerMonth) {
                    total += t;
                }
                return total;
            }
        }

        /// <summary>Total in-world minutes in a single day.</summary>
        public int MinutesPerDay => hoursPerDay * minutesPerHour;

        /// <summary>Validates all calendar parameters. Throws ArgumentException on invalid configuration.</summary>
        public void Validate() {
            if(secondsPerFullDay <= 0f) {
                throw new ArgumentException("SecondsPerFullDay must be > 0");
            }
            if(hoursPerDay <= 0) {
                throw new ArgumentException("HoursPerDay must be > 0");
            }
            if(minutesPerHour <= 0) {
                throw new ArgumentException("MinutesPerHour must be > 0");
            }
            if(daysPerMonth == null || daysPerMonth.Length == 0) {
                throw new ArgumentException("DaysPerMonth must have at least one entry");
            }
            if(monthNames == null || monthNames.Length != daysPerMonth.Length) {
                throw new ArgumentException("MonthNames length must match DaysPerMonth length");
            }
            for(var i = 0; i < daysPerMonth.Length; i++) {
                if(daysPerMonth[i] <= 0) {
                    throw new ArgumentException($"DaysPerMonth[{i}] must be > 0");
                }
            }
            if(startMonth < 0 || startMonth >= daysPerMonth.Length) {
                throw new ArgumentException("StartMonth out of range");
            }
            if(startDay < 0 || startDay >= daysPerMonth[startMonth]) {
                throw new ArgumentException("StartDay out of range for StartMonth");
            }
            if(startHour < 0 || startHour >= hoursPerDay) {
                throw new ArgumentException("StartHour out of range");
            }
            if(startMinute < 0 || startMinute >= minutesPerHour) {
                throw new ArgumentException("StartMinute out of range");
            }
        }
    }
}
