using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Windows.Forms;
using Baza_Reklam.Classes;
using Baza_Reklam.Classes.Interfaces;
using Baza_Reklam.Classes.Helpers;

namespace Baza_Reklam
{
    public partial class ProvisionForm : Form, IForm
    {
        private short rok;
        private short miesiac;
        private int agencja;

        private bool? _isProvisionBlocked;

        /// <summary>
        /// Klasa pomocnicza do wyświetlania w 0 - 2 w gridzie
        /// </summary>
        class Ocena
        {
            private int label;
            private Single value;

            public int Label
            {
                get { return label; }
                set { label = value; }
            }

            public Single Value
            {
                get { return value; }
                set { this.value = value; }
            }

            public Ocena(int l, Single v)
            {
                label = l;
                value = v;
            }
        }

        private static ProvisionForm provisionForm;

        public static ProvisionForm GetProvisionForm(MDIBazaReklam parent)
        {
            if (provisionForm == null)
            {
                provisionForm = new ProvisionForm(parent);
            }
            return provisionForm;
        }

        public ProvisionForm(Form parent)
        {
            InitializeComponent();

            MdiParent = parent;

            pLANTableAdapter.Connection.ConnectionString = ConnString.getConnString().Value;
            aGENCITableAdapter.Connection.ConnectionString = ConnString.getConnString().Value;
            agencjeTableAdapter1.Connection.ConnectionString = ConnString.getConnString().Value;

            //bindowanie ocen z comboBoxColumn
            List<Ocena> oceny = new List<Ocena>();
            oceny.Add(new Ocena(0, 0));
            oceny.Add(new Ocena(1, 50));
            oceny.Add(new Ocena(2, 100));

            OCENAComboCoxColumn.DataSource = oceny;
            OCENAComboCoxColumn.DisplayMember = "label";
            OCENAComboCoxColumn.ValueMember = "value";

            dodajPlanToolStripButton.Enabled = User.Instance().IsKierownik;
            usunToolStripButton.Enabled = User.Instance().IsKierownik;
        }

        private void ProvisionForm_Load(object sender, EventArgs e)
        {
            rokToolStripTextBox.Text = DateTime.Today.Year.ToString();
            msToolStripTextBox.Text = DateTime.Today.Month.ToString();

            ((ComboBox)agencjaToolStripComboBox.Control).DataSource = agencjeTableAdapter1.GetData();
            ((ComboBox)agencjaToolStripComboBox.Control).DisplayMember = "Symbol";
            ((ComboBox)agencjaToolStripComboBox.Control).ValueMember = "ID_Agencji";

            ((ComboBox)agencjaToolStripComboBox.Control).SelectedValue = User.Instance().IdAgencji;

            if (!User.Instance().IsKierownik)
            {
                agencjaToolStripComboBox.Enabled = false;
                pLANBindingSource.Filter = "Symbol = '" + User.Instance().Login + "'";
            }
        }

        /// <summary>
        ///     Krok 1
        ///     Wylicza i zapisuje prowizję agenta do planu
        /// </summary>
        private void zapiszToolStripButton_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            SqlConnection conn = null;
            SqlTransaction transaction = null;

            try
            {
                SaveResult();

                conn = new SqlConnection(ConnString.getConnString().Value);
                conn.Open();
                transaction = conn.BeginTransaction();

                SqlCommand command = new SqlCommand();
                command.CommandType = CommandType.StoredProcedure;
                command.Connection = conn;
                command.Transaction = transaction;

                //Krok 1
                //oblicza procent prowizji i wykonany budzet, generuje dane dla wybranego biura za wybrany miesiac
                command.CommandText = "PROC_WYLICZ_I_ZAPISZ_DANE_O_KONTAKTACH_I_BUDZECIE";
                command.Parameters.AddWithValue("@rok", rok);
                command.Parameters.AddWithValue("@ms", miesiac);
                command.ExecuteNonQuery();

                //TODO: Zastanowic sie, czy ten krok jest jeszcze w ogole potrzebny... 
                //TODO: Nawet gdyby zaplacono za fakture z 2008 to i tak nie bedzie sie liczyc do prowizji
                //Krok 2
                //nalicza prowizje dla faktur wystawionych przed 2009
                command.CommandText = "PROC_WYLICZ_I_ZAPISZ_PROWIZJE_DO_REKLAM";
                command.ExecuteNonQuery();

                //Krok 3
                //Wylicza i zapisuje prowizję agenta do planu
                command.CommandText = "PROC_WYLICZ_I_ZAPISZ_PROWIZJE_AGENTA_DO_PLANU";
                command.Parameters.AddWithValue("@id_Agencji", agencja);
                command.ExecuteNonQuery();

                transaction.Commit();
                MessageBox.Show("Dane pobrano i prowizja została zapisana.", "Baza Reklam - Prowizje");
            }
            catch
            {
                if (transaction != null)
                    transaction.Rollback();
                throw;
            }
            finally
            {
                if (conn != null) conn.Close();

                rEKLAMADataSet.PLAN.Clear();
                pLANTableAdapter.FillByAgencja(rEKLAMADataSet.PLAN, rok, miesiac, agencja);

                Cursor = Cursors.Default;
            }
        }

        /// <summary>
        ///     Krok 2
        ///     dyrektor ma prawo zmienic recznie procent prowizji, dodac ocene dla wybranego handlowca, nanosi poprawione dane
        /// </summary>
        private void naniesNaReklamyToolStripButton_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            SqlCommand command = new SqlCommand();

            command.Connection = new SqlConnection(ConnString.getConnString().Value);

            command.CommandType = CommandType.StoredProcedure;

            command.CommandText = "PROC_WYLICZ_I_ZAPISZ_PROWIZJE";
            command.Parameters.AddWithValue("@rok", rok);
            command.Parameters.AddWithValue("@ms", miesiac);
            command.Parameters.AddWithValue("@idAgencji", agencja);

            command.Connection.Open();

            SqlTransaction transaction = command.Connection.BeginTransaction();

            command.Transaction = transaction;

            try
            {
                SaveResult();

                command.ExecuteNonQuery();
                transaction.Commit();
                MessageBox.Show("Prowizja została naniesiona na zlecenia", "Baza Reklam - Prowizje");
            }
            catch
            {
                transaction.Rollback();
                throw;
            }
            finally
            {
                command.Connection.Close();
                Cursor = Cursors.Default;
            }
        }

        private void dodajPlanToolStripButton_Click(object sender, EventArgs e)
        {
            OcenaAddForm oaf = new OcenaAddForm();
            oaf.Show();
        }

        private void usunToolStripButton_Click(object sender, EventArgs e)
        {
            if (pLANBindingSource.Current != null)
            {
                if (MessageBox.Show("Czy na pewno usunąć rekord?", "", MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    pLANBindingSource.RemoveCurrent();
                    pLANBindingSource.EndEdit();
                    pLANTableAdapter.Update(rEKLAMADataSet.PLAN);
                }
            }
        }

        private void zapiszDaneToolStripButton_Click(object sender, EventArgs e)
        {
            Cursor = Cursors.WaitCursor;

            if (Validate())
            {
                if (prowizjeDataGridView.SelectedCells.Count!=1)
                {
                    MessageBox.Show("Proszę zaznaczyć tylko jedną komórkę.");
                    Cursor = Cursors.Default;
                    return;
                }
                
                SaveResult();

                MessageBox.Show("Zmiany zapisane");
            }
            Cursor = Cursors.Default;
        }

        /// <summary>
        /// Podsumowuje budżet do wykonania
        /// </summary>
        private void UzupelnijBDsuma()
        {
            int kasa = 0;
            foreach (DataRowView r in pLANBindingSource.List)
            {
                kasa += Convert.ToInt32(r["BUDZET"]);
            }
            BDsumaTextBox.Text = String.Format("{0:C}", kasa);
        }

        /// <summary>
        /// Podsumowuje budżet wykonany
        /// </summary>
        private void UzupelnijBudzetWykonanySuma()
        {
            int kasa = 0;
            foreach (DataRowView r in pLANBindingSource.List)
            {
                kasa += Convert.ToInt32(r["W_BUDZET"]);
            }
            BDWykonanySumaTextBox.Text = String.Format("{0:C}", kasa);
        }

        private void pLANBindingSource_ListChanged(object sender, ListChangedEventArgs e)
        {
            UzupelnijBDsuma();
            UzupelnijBudzetWykonanySuma();
        }

        private void szukajToolStripButton_Click(object sender, EventArgs e)
        {
            if (!string.IsNullOrEmpty(rokToolStripTextBox.Text))
            {
                short i;
                if (!Int16.TryParse(rokToolStripTextBox.Text, out i))
                {
                    MessageBox.Show("Podaj prawidłowy rok.");
                    Cursor = Cursors.Default;
                    return;
                }
            }
            else
            {
                MessageBox.Show("Podaj prawidłowy rok.");
                Cursor = Cursors.Default;
                return;
            }

            if (!string.IsNullOrEmpty(msToolStripTextBox.Text))
            {
                short i;
                if (!Int16.TryParse(msToolStripTextBox.Text, out i))
                {
                    MessageBox.Show("Podaj prawidłowy miesiąc.");
                    Cursor = Cursors.Default;
                    return;
                }
            }
            else
            {
                MessageBox.Show("Podaj prawidłowy miesiąc.");
                Cursor = Cursors.Default;
                return;
            }

            if (((ComboBox)agencjaToolStripComboBox.Control).SelectedValue == null)
            {
                MessageBox.Show("Wybierz agencję");
                return;
            }

            rok = Convert.ToInt16(rokToolStripTextBox.Text);
            miesiac = Convert.ToInt16(msToolStripTextBox.Text);
            agencja = Convert.ToInt32(((ComboBox)agencjaToolStripComboBox.Control).SelectedValue);

            Uprawnienia(agencja, rok, miesiac);

            sLOWNIKDataSet.AGENCI.Clear();
            rEKLAMADataSet.PLAN.Clear();

            aGENCITableAdapter.FillByIdAgencji(sLOWNIKDataSet.AGENCI, agencja);
            pLANTableAdapter.FillByAgencja(rEKLAMADataSet.PLAN, rok, miesiac, agencja);


            btnBlockProvision.Visible = User.Instance().IsKierownik;
            if (!User.Instance().IsKierownik) return;

            _isProvisionBlocked =
                new ProvisionHelper(ConnString.getConnString().Value).IsProvisionBlockedInDb(agencja, rok, miesiac);

            SetBlockProvisionButtonText(_isProvisionBlocked.Value);
        }

        private void Uprawnienia(int agencyId, int year, int month)
        {
            if (IsProvisionBlocked(agencyId, year, month, User.Instance().IsKierownik))
            {
                OCENAComboCoxColumn.Visible = false;
                oCENADataGridViewTextBoxColumn.Visible = true;

                prowizjeDataGridView.ReadOnly = true;
                usunToolStripButton.Enabled = false;
                naniesNaReklamyToolStripButton.Enabled = false;
                zapiszDaneToolStripButton.Enabled = false;
                zapiszToolStripButton.Enabled = false;
            }
            else
            {
                OCENAComboCoxColumn.Visible = true;
                oCENADataGridViewTextBoxColumn.Visible = false;
                prowizjeDataGridView.ReadOnly = false;

                usunToolStripButton.Enabled = true;
                naniesNaReklamyToolStripButton.Enabled = true;
                zapiszDaneToolStripButton.Enabled = true;
                zapiszToolStripButton.Enabled = true;
            }
        }

        private bool IsProvisionBlocked(int agencyId, int year, int month, bool isKierownik)
        {
            ProvisionHelper provisionHelper = new ProvisionHelper(ConnString.getConnString().Value);
            return provisionHelper.IsProvisionBlocked(agencyId, year, month, isKierownik);
        }

        private void prowizjeDataGridView_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            if (prowizjeDataGridView.Columns[e.ColumnIndex].Name != "PR_PROWIZJI") return;

            CorrectBonusPercentage(e.ColumnIndex, e.RowIndex);
        }

        private void CorrectBonusPercentage(int column, int row)
        {
            if (prowizjeDataGridView.Columns[column].Name != "PR_PROWIZJI") return;

            if (prowizjeDataGridView.Columns[column].Name == "PR_PROWIZJI")
            {
                if (Convert.ToDecimal(prowizjeDataGridView[column, row].Value) >= 1)
                {
                    prowizjeDataGridView[column, row].Value =
                        Convert.ToDecimal(prowizjeDataGridView[column, row].Value) / 100;
                }
            } 
        }

        private void SaveResult()
        {
            CorrectBonusPercentage(prowizjeDataGridView.SelectedCells[0].ColumnIndex, prowizjeDataGridView.SelectedCells[0].RowIndex);
            pLANBindingSource.EndEdit();
            pLANTableAdapter.Update(rEKLAMADataSet.PLAN);
        }

        /// <summary>
        /// Zamienia wpisaną liczbę do decimal
        /// </summary>
        private void prowizjeDataGridView_CellLeave(object sender, DataGridViewCellEventArgs e)
        {
            if (!Validate())
            {
                if (prowizjeDataGridView.Columns[e.ColumnIndex].Name == "PR_PROWIZJI")
                    MessageBox.Show("Proszę wprowadzić prowizję bez znaku % - tylko wartość liczbową");
                else
                    MessageBox.Show("Proszę wprowadzić poprawne dane");

                return;
            }

            CorrectBonusPercentage(e.ColumnIndex, e.RowIndex);

            ukrytyLabel.Select();
            prowizjeDataGridView.EndEdit();
            pLANBindingSource.EndEdit();

            REKLAMADataSet.PLANDataTable changes = rEKLAMADataSet.PLAN.GetChanges(DataRowState.Modified) as
                 REKLAMADataSet.PLANDataTable;

            if (changes != null)
            {
                pLANBindingSource.EndEdit();
                pLANTableAdapter.Update(rEKLAMADataSet.PLAN);
            }
        }

        private void prowizjeDataGridView_Leave(object sender, EventArgs e)
        {
            prowizjeDataGridView.EndEdit();

            REKLAMADataSet.PLANDataTable changes = rEKLAMADataSet.PLAN.GetChanges(DataRowState.Modified) as
                REKLAMADataSet.PLANDataTable;

            if (changes != null && Validate())
            {
                pLANBindingSource.EndEdit();
                pLANTableAdapter.Update(rEKLAMADataSet.PLAN);
            }
        }

        //TODO: Wprowadzić sensowniejszą walidację danych
        private void prowizjeDataGridView_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {

        }

        private void ProvisionForm_Leave(object sender, EventArgs e)
        {
            prowizjeDataGridView.EndEdit();

            REKLAMADataSet.PLANDataTable changes =
                    rEKLAMADataSet.PLAN.GetChanges(DataRowState.Modified) as REKLAMADataSet.PLANDataTable;

            if (changes != null && Validate())
            {
                pLANBindingSource.EndEdit();
                pLANTableAdapter.Update(rEKLAMADataSet.PLAN);
            }
        }

        private void printToolStripButton_Click(object sender, EventArgs e)
        {
            PrintDGV.Print_DataGridView(prowizjeDataGridView, 50);
        }

        public void CloseForm()
        {
            provisionForm = null;
        }

        private void btnBlockProvision_Click(object sender, EventArgs e)
        {
            if (!User.Instance().IsKierownik) return;

            if (!_isProvisionBlocked.HasValue) return;

            ProvisionHelper provisionHelper = new ProvisionHelper(ConnString.getConnString().Value);
            provisionHelper.SetProvision(!_isProvisionBlocked.Value, agencja, rok, miesiac, User.Instance().Login);

            _isProvisionBlocked = !_isProvisionBlocked.Value;

            SetBlockProvisionButtonText(_isProvisionBlocked.Value);

            Uprawnienia(agencja, rok, miesiac);

            sLOWNIKDataSet.AGENCI.Clear();
            rEKLAMADataSet.PLAN.Clear();

            aGENCITableAdapter.FillByIdAgencji(sLOWNIKDataSet.AGENCI, agencja);
            pLANTableAdapter.FillByAgencja(rEKLAMADataSet.PLAN, rok, miesiac, agencja);

            if (_isProvisionBlocked.Value)
                SendEmailNotification();
        }

        private void SetBlockProvisionButtonText(bool isBlocked)
        {
            btnBlockProvision.Text = isBlocked ? "Odblokuj edycję prowizji" : "Zablokuj edycję prowizji";
            btnBlockProvision.Checked = isBlocked;
        }

        private void SendEmailNotification()
        {
            string selectedAgencja = agencjaToolStripComboBox.Control.Text;
            ISmtpConfiguration smtpConfig = new SmtpConfiguration();
            IEmailSender emailSender = new EmailSender(smtpConfig);
            emailSender.From = ConfigurationHelper.GetSettingByKey("Application.Email.From");
            emailSender.To.AddRange(ConfigurationHelper.GetSettingByKey("Application.Email.Prowizje.To").Split(';'));
            emailSender.Subject = string.Format(ConfigurationHelper.GetSettingByKey("Application.Email.Prowizje.Subject"), selectedAgencja);
            emailSender.Body = string.Format(ConfigurationHelper.GetSettingByKey("Application.Email.Prowizje.Body"), selectedAgencja, User.Instance().Imie + " " + User.Instance().Nazwisko, "\n", DateTime.Now);
            emailSender.Send();
        }
    }
}