using Costumes;
using Employees;
using Offers;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.SceneManagement;
using Utils;

namespace Managers
{
    public class GameManager : SingletonComponent<GameManager>
    {
        [SerializeField] CostumesManager costumeManager;
        [SerializeField] EmployeeManager employeeManager;
        [SerializeField] OffersManager offersManager;
        [SerializeField] UI.Notification.NotificationManager notificationManager;


        [SerializeField] UnityEvent onGameOver;

        public List<Employee> OurEmployees => employeeManager.OurEmployees;
        public List<Employee> HireEmployees => employeeManager.HireEmployees;

        private void Start()
        {
            Calendar.Instance.SubscribeOnWeekEnded((_) => PaySalary());
        }

        public bool CanAcceptOffer(Offer offerData)
        {
            if (offerData.OfferState != OfferState.Created)
                return false;

            //return true;

            return costumeManager.IsFreeCostumes(offerData.AnimatorsCount, offerData.StartTime, offerData.EndTime)
                     && employeeManager.IsFreeEmployees(offerData.AnimatorsCount, offerData.StartTime, offerData.EndTime);
        }

        public void AcceptOffer(Offer offerData)
        {
            costumeManager.BookCostumes(offerData.AnimatorsCount, offerData.StartTime, offerData.EndTime);
            employeeManager.BookEmployees(offerData.AnimatorsCount, offerData.StartTime, offerData.EndTime);

            offersManager.AcceptOffer(offerData);
        }

        public void RejectOffer(Offer offerData) => offersManager.RejectOffer(offerData);

        public void AddNewOffer(Offer offer)
        {
            offersManager.AddNewOffer(offer);
        }

        #region Costumes Section

        public List<(CostumeType, int)> GetCostumeByType()
        {
            return costumeManager.GetCostumeByType();
        }

        public void BuyCostume(Costumes.CostumeType type)
        {
            costumeManager.BuyCostume(type);
        }

        public void SellCostume(Costumes.CostumeType type)
        {
            costumeManager.SellCostume(type);
        }

        public void GenerateCostumesFromSave()
        {
            costumeManager.GenerateCostumesFromSave();
        }

        #endregion


        #region Employee Section
        public void ReleaseOurWorker(Employee worker)
        {
            employeeManager.ReleaseOurEmployee(worker);
        }

        public void ReleaseHireWorker(Employee worker)
        {
            employeeManager.ReleaseHireEmployee(worker);
        }

        public void UpgradeEmployeeTime(Employee worker)
        {
            employeeManager.UpgradeWorkerTime(worker);
        }

        public void UpgradeEmployeeEvents(Employee worker)
        {
            employeeManager.UpgradeWorkerEvents(worker);
        }

        public void HireEmployee(Employee worker)
        {
            employeeManager.HireEmployee(worker);
        }

        public void GenerateEmployeesFromSave()
        {
            employeeManager.GenerateEmployeesFromSave();
        }

        public List<EmployeeData> GenerateEmployees(int amount) => employeeManager.GenerateRandomEmployeeDatas(amount);

        public List<Costumes.CostumeData> GenerateCostumes(List<Costumes.CostumeStartData> startData) => costumeManager.GenerateCostumeDatas(startData);
        #endregion

        public List<Offer> GetCreatedOffers() => offersManager.GetCreatedOffers();

        public List<Offer> GetAcceptedOffers() => offersManager.GetAcceptedOffers();


        public List<Offer> GetCompletedOffers() => offersManager.GetCompletedOffers();

        public void SendOrderNotification(Offer offer) => notificationManager.SendOfferCompletedNotification(offer);

        [ContextMenu("PaySalary")]
        void PaySalary()
        {
            int salary = (int) OurEmployees.Sum(x => x.Data.salary);
            DataManager.Instance.Budget -= salary;
            SendSalaryNotification(salary);
        }

        public void GameOver() => onGameOver.Invoke();

        public void SendSalaryNotification(int salary) => notificationManager.SendSalaryNotification(salary);
    
        public void CloseOffer(Offer offer)
        {
            offersManager.CloseOffer(offer);
        }

        public void CancelOffer(Offer offer)
        {
            offersManager.CancelOffer(offer);

            costumeManager.UnBookCostume(offer);
            employeeManager.UnBookEmployee(offer);
        }

        public void ResetGame()
        {
            DataManager.Instance.ResetProgress();

            SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
        }
    }
}