namespace Generator_Class_BD
{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Data.SqlClient;
    using System.Diagnostics;
    using Generator_Class_BD.Clases.Consultas;
    using System.Linq;
    using Ookii.Dialogs.WinForms;

    public partial class FormSelector : Form
    {
        public FormSelector()
        {
            InitializeComponent();
        }

        private string fileName = "";
        private Plantilla obj = new Plantilla();
        public string tablaSeleccionada;
        public List<Consulta> listaConsultas;
        public List<Consulta> listaConsultasFront;

        private void btnPrevius_Click(object sender, EventArgs e)
        {
            Login frm = new Login();
            frm.Show();
            this.Hide();
        }

        private void Form2_Load(object sender, EventArgs e)
        {
            dgvTablas.DataSource = GetTables().Tables[0];
            txtRuta.Text = @"C:\";
            folderBrowserDialog1.SelectedPath = @"C:\";

            this.chkListaMetodo.Items.Add("1.Api", true);
            this.chkListaMetodo.Items.Add("2.Negocio", true);
            this.chkListaMetodo.Items.Add("3.Datos", true);
            this.chkListaMetodo.Items.Add("4.Interfaces Comunes", true);

            AjustarVentanaRelaciones();

            listaConsultas = new List<Consulta>();
            listaConsultasFront = new List<Consulta>();
        }

        public DataSet GetTables()
        {
            SqlCommand cmd = new SqlCommand();
            SqlDataAdapter da = new SqlDataAdapter();
            DataSet ds = new DataSet();

            try
            {
                SqlConnection con = new SqlConnection(lblstrConexion.Text);
                con.Open();
                cmd.Connection = con;
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = $"Use {lblDataBase.Text} {Recursos.RecursosBD.QueryTablas}";
                da.SelectCommand = cmd;
                con.Close();
                da.Fill(ds);
            }
            catch (SqlException x)
            {
                MessageBox.Show("Error de SQL :" + x.Message);
            }
            catch (Exception y)
            {
                MessageBox.Show("Error :" + y.Message);
            }
            return ds;
        }

        public DataSet GetColumns(string TableName)
        {
            SqlCommand cmd = new SqlCommand();
            SqlDataAdapter da = new SqlDataAdapter();
            DataSet ds = new DataSet();

            try
            {
                SqlConnection con = new SqlConnection(lblstrConexion.Text);
                con.Open();
                cmd.Connection = con;
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = $"Use {lblDataBase.Text} {Recursos.RecursosBD.QueryObtenerColumnas}";
                cmd.Parameters.Add("@TableName", SqlDbType.NVarChar, 50).Value = TableName;
                da.SelectCommand = cmd;
                da.Fill(ds);
            }
            catch (SqlException x)
            {
                MessageBox.Show("Error de SQL :" + x.Message);
            }
            catch (Exception y)
            {
                MessageBox.Show("Error :" + y.Message);
            }
            return ds;
        }

        public DataSet ObtenerColumnasCompuestas(string NombreTabla)
        {
            SqlCommand cmd = new SqlCommand();
            SqlDataAdapter da = new SqlDataAdapter();
            DataSet ds = new DataSet();
            try
            {
                SqlConnection con = new SqlConnection(lblstrConexion.Text);
                con.Open();
                cmd.Connection = con;
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = $"Use { lblDataBase.Text} {string.Format(Recursos.RecursosBD.QueryCamporPorTablaRelacionados, NombreTabla)}";
                da.SelectCommand = cmd;
                con.Close();
                da.Fill(ds);
            }
            catch (SqlException x)
            {
                MessageBox.Show("Error de SQL :" + x.Message);
            }
            catch (Exception y)
            {
                MessageBox.Show("Error :" + y.Message);
            }
            return ds;
        }

        private void dgvTablas_CellEnter(object sender, DataGridViewCellEventArgs e)
        {
            dgvColumn.DataSource = GetColumns(dgvTablas.Rows[e.RowIndex].Cells["colTab_Nombre"].Value.ToString()).Tables[0];
        }

        private void dgvTablas_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                if (dgvTablas.Rows[e.RowIndex].Cells["colTab_Select"].Value == null)
                    dgvTablas.Rows[e.RowIndex].Cells["colTab_Select"].Value = true;
                else if (Boolean.Parse(dgvTablas.Rows[e.RowIndex].Cells["colTab_Select"].Value.ToString()) == true)
                    dgvTablas.Rows[e.RowIndex].Cells["colTab_Select"].Value = false;
                else if (Boolean.Parse(dgvTablas.Rows[e.RowIndex].Cells[0].Value.ToString()) == false)
                    dgvTablas.Rows[e.RowIndex].Cells["colTab_Select"].Value = true;
                DataTable dataRelaciones = CargarGridRelaciones(dgvTablas.Rows[e.RowIndex].Cells).Tables[0];
                dgvRelaciones.DataSource = dataRelaciones;
                this.tablaSeleccionada = dgvTablas.Rows[e.RowIndex].Cells["colTab_Nombre"].Value.ToString();
            }
        }

        private void checkBox1_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBox1.Checked)
            {
                foreach (DataGridViewRow row in dgvTablas.Rows)
                {
                    row.Cells["colTab_Select"].Value = true;
                }
            }
            else
            {
                foreach (DataGridViewRow row in dgvTablas.Rows)
                {
                    row.Cells["colTab_Select"].Value = false;
                }
            }
        }

        private void btnCarpeta_Click(object sender, EventArgs e)
        {
            VistaFolderBrowserDialog dlg = new VistaFolderBrowserDialog();
            dlg.ShowNewFolderButton = true;

            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                txtRuta.Text = dlg.SelectedPath;
            }
        }

        private void btnGenerar_Click(object sender, EventArgs e)
        {
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            this.Cursor = Cursors.WaitCursor;
            if (ValidarCampos())
            {
                foreach (DataGridViewRow row in dgvTablas.Rows)
                {
                    if (row.Cells["colTab_Select"].Value != null)
                    {
                        if (Boolean.Parse(row.Cells["colTab_Select"].Value.ToString()) == true)
                        {
                            string sEntidad = row.Cells["colTab_Nombre"].Value.ToString();
                            DataSet dsCol = GetColumns(sEntidad);

                            for (int i = 0; i < chkListaMetodo.CheckedItems.Count; i++)
                            {
                                if (chkListaMetodo.CheckedItems[i].ToString().Equals("1.Api"))
                                {
                                    Clases.NetCore._1.Controladores.Controladores.GenerarControlador(sEntidad, dsCol, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                                }

                                if (chkListaMetodo.CheckedItems[i].ToString().Equals("2.Negocio"))
                                {
                                    Clases.NetCore._2.Negocio.Negocio.GenerarBO(sEntidad, dsCol, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                                    Clases.NetCore._2.Negocio.Negocio.GenerarBL(sEntidad, dsCol, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                                }

                                if (chkListaMetodo.CheckedItems[i].ToString().Equals("3.Datos"))
                                {
                                    Clases.NetCore._3.Datos.Datos.GenerarDOEntidades(sEntidad, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                                    Clases.NetCore._3.Datos.Datos.GenerarDAL(sEntidad, txtRuta.Text, dsCol, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                                }

                                if (chkListaMetodo.CheckedItems[i].ToString().Equals("4.Interfaces Comunes"))
                                {
                                    Clases.NetCore._4.Interfaces_Comunes.InterfacesComunes.GenerarDTO(sEntidad, dsCol, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                                    Clases.NetCore._4.Interfaces_Comunes.InterfacesComunes.GenerarAcciones(sEntidad, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                                }
                            }
                        }
                    }
                }
                GenerarConsultas();
                stopwatch.Stop();

                MessageBox.Show("Termino el Proceso Tempo: " + stopwatch.Elapsed);
            }
            this.Cursor = Cursors.Default;
        }

        private bool ValidarCampos()
        {
            if (TxtSolucion.Text == "")
            {
                MessageBox.Show("El nombre de la solucion es obligatorio");
                return false;
            }

            if (txtCopyright.Text == "")
            {
                MessageBox.Show("El campo Copyright es obligatorio");
                return false;
            }

            if (txtAutor.Text == "")
            {
                MessageBox.Show("El nombre del autor es obligatorio");
                return false;
            }
            if (dgvTablas.Rows.Count > 0)
            {
                int i = 0;
                foreach (DataGridViewRow row in dgvTablas.Rows)
                {
                    if (row.Cells[0].Value != null)
                    {
                        if (Boolean.Parse(row.Cells[0].Value.ToString()) == true)
                        {
                            i++;
                        }
                    }
                }
                if (i == 0)
                {
                    MessageBox.Show("Seleccione al menos una Tabla");
                    return false;
                }
            }

            if (chkListaMetodo.CheckedItems.Count == 0)
            {
                MessageBox.Show("Debe seleccionar al menos una capa");
                return false;
            }

            IEnumerable<RadioButton> allRadios = groupBox6.Controls.OfType<RadioButton>();
            if (!allRadios.Any(rb => rb.Checked))
            {
                MessageBox.Show("Debe seleccionar un Framework");
                return false;
            }
            return true;
        }

        private void GenerarConsultas()
        {
            listaConsultas.ForEach(consulta =>
            {
                consulta.ListaTablasRelacionadas.ForEach(tabla =>
                {
                    if (chkListaMetodo.CheckedItems.Contains("1.API"))
                    {
                        Clases.NetCore._1.Controladores.Controladores.GenerarControladorConsulta(consulta, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                    }

                    if (chkListaMetodo.CheckedItems.Contains("2.Negocio"))
                    {
                        Clases.NetCore._2.Negocio.Negocio.GenerarBOConsultas(consulta, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                        Clases.NetCore._2.Negocio.Negocio.GenerarBLConsultas(consulta, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                    }

                    if (chkListaMetodo.CheckedItems.Contains("3.Datos"))
                    {
                        Clases.NetCore._3.Datos.Datos.GenerarDOConsultas(consulta, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                        Clases.NetCore._3.Datos.Datos.GenerarDALConsultas(consulta, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                    }

                    if (chkListaMetodo.CheckedItems.Contains("4.Interfaces Comunes"))
                    {
                        Clases.NetCore._4.Interfaces_Comunes.InterfacesComunes.GenerarConsultasDTO(consulta, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                        Clases.NetCore._4.Interfaces_Comunes.InterfacesComunes.GenerarAccionesConsultas(consulta.NombreObjeto, txtRuta.Text, TxtSolucion.Text, txtAutor.Text, txtCopyright.Text);
                    }
                });
            });
        }

        private void txtClaseConexion_KeyPress(object sender, KeyPressEventArgs e)
        {
            if ((e.KeyChar >= 48 && e.KeyChar <= 57))
            {
                e.Handled = true;
            }
        }

        private string MetodoClaseConexion(string vClaseConexion)
        {
            StringBuilder vc = new StringBuilder();
            vc.Append("using System;\n");
            vc.Append("using System.Data;\n");
            vc.Append("using System.Data.SqlClient;\n");
            vc.Append("\n");
            vc.Append("public class " + vClaseConexion + "\n");
            vc.Append("{\n");
            vc.Append("\tpublic " + vClaseConexion + "() { }\n\n");
            vc.Append("\tpublic SqlConnection getConexion()\n");
            vc.Append("\t{\n");
            vc.Append("\t\ttry\n");
            vc.Append("\t\t{\n");
            vc.Append("\t\t\tSqlConnection con = new SqlConnection(\"" + lblstrConexion.Text + "\");\n");
            vc.Append("\t\t\treturn con;\n");
            vc.Append("\t\t}\n");
            vc.Append("\t\tcatch (SqlException e) { Console.WriteLine(\"Error de SQL :\" + e.Message); }\n");
            vc.Append("\t\tcatch (Exception e) { Console.WriteLine(\"Error :\" + e.Message); }\n");
            vc.Append("\t\treturn null;\n");
            vc.Append("\t}\n");
            vc.Append("}\n");
            return vc.ToString();
        }

        private void CrearArchivo(string sFileName, string path, StringBuilder cuerpo)
        {
            Directory.CreateDirectory(path);
            StreamWriter writer = File.CreateText(sFileName);
            writer.WriteLine(cuerpo.ToString());
            writer.Close();
        }

        private void btnSalir_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void btnView_Click(object sender, EventArgs e)
        {
            frmView frm = new frmView();
            frm.txtViewClase.Text = MetodoClaseConexion(txtClaseConexion.Text);
            frm.Show();
        }

        private void TxtSolucion_TextChanged(object sender, EventArgs e)
        {
        }

        private void AjustarVentanaRelaciones()
        {
            Width = Width == 1130 ? 731 : 1130;
            tabOpciones.SelectedTab = tabRelaciones;
            tabOpciones.Visible = Width == 1130 ? true : false;
        }

        private DataSet CargarGridRelaciones(DataGridViewCellCollection celdasTablas)
        {
            SqlCommand cmd = new SqlCommand();
            SqlDataAdapter da = new SqlDataAdapter();
            DataSet ds = new DataSet();
            string nombreTabla = $"{celdasTablas["colSchema"].Value.ToString()}.{celdasTablas["colTab_Nombre"].Value.ToString()}";

            try
            {
                SqlConnection con = new SqlConnection(lblstrConexion.Text);
                con.Open();
                cmd.Connection = con;
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = $"Use {lblDataBase.Text} {string.Format(Recursos.RecursosBD.QueryRelacionesTabla, nombreTabla)}";
                da.SelectCommand = cmd;
                da.Fill(ds);
                con.Close();
            }
            catch (SqlException x)
            {
                MessageBox.Show("Error de SQL :" + x.Message);
            }
            catch (Exception y)
            {
                MessageBox.Show("Error :" + y.Message);
            }
            return ds;
        }

        private void dgvRelaciones_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            var senderGrid = (DataGridView)sender;

            if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >= 0)
            {
                if (senderGrid.Columns[e.ColumnIndex].Name == "colbtnSeleccionarCampos")
                {
                    colbtnSeleccionarCampos_Click(e);
                }
            }
        }

        private void colbtnSeleccionarCampos_Click(DataGridViewCellEventArgs e)
        {
        }

        private void btnAgregarRelacion_Click(object sender, EventArgs e)
        {
            bool filaSeleccionada = false;

            if (txtNombreObjeto.Text.Trim().Length == 0)
            {
                MessageBox.Show("Nombre de objeto no válido", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            foreach (DataGridViewRow fila in dgvRelaciones.Rows)
            {
                filaSeleccionada = dgvRelaciones.Rows[fila.Index].Cells["colSelect"].Value == null ? false : (bool)dgvRelaciones.Rows[fila.Index].Cells["colSelect"].Value;

                if (filaSeleccionada)
                    break;
            }

            if (!filaSeleccionada)
            {
                MessageBox.Show("Debe seleccionar alguna relación para la tabla", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            CargarListaRelaciones();
        }

        private void CargarListaRelaciones()
        {
            listaConsultas.Remove(listaConsultas.FirstOrDefault(x => x.NombreObjeto == txtNombreObjeto.Text));

            foreach (DataGridViewRow fila in dgvRelaciones.Rows)
            {
                bool filaSeleccionada = dgvRelaciones.Rows[fila.Index].Cells["colSelect"].Value == null ? false : (bool)dgvRelaciones.Rows[fila.Index].Cells["colSelect"].Value;

                if (filaSeleccionada)
                {
                    Consulta objetoConsultaEditar = listaConsultas.Where(x => x.NombreObjeto == txtNombreObjeto.Text).FirstOrDefault();

                    if (objetoConsultaEditar != null)
                    {
                        objetoConsultaEditar.ListaTablasRelacionadas.Add(new TablaRelacionada
                        {
                            ListaCampos = new List<Campo>(),
                            TablaNombre = dgvRelaciones.Rows[fila.Index].Cells["colTabla"].Value.ToString(),
                            IdFK = dgvRelaciones.Rows[fila.Index].Cells["colFKId"].Value.ToString(),
                            ListaColumnasRelacion = ObtenerColumnasRelacion(dgvRelaciones.Rows[fila.Index].Cells["colFkId"].Value.ToString())
                        });
                    }
                    else
                    {
                        listaConsultas.Add(new Consulta
                        {
                            NombreObjeto = txtNombreObjeto.Text,
                            TablaPrincipal = dgvTablas.SelectedRows[0].Cells["colTab_Nombre"].Value.ToString(),
                            ListaTablasRelacionadas = new List<TablaRelacionada>()
                            {
                                new TablaRelacionada
                                {
                                    ListaCampos = new List<Campo>(),
                                    TablaNombre = dgvRelaciones.Rows[fila.Index].Cells["colTabla"].Value.ToString(),
                                    IdFK = dgvRelaciones.Rows[fila.Index].Cells["colFKId"].Value.ToString(),
                                    ListaColumnasRelacion = ObtenerColumnasRelacion(dgvRelaciones.Rows[fila.Index].Cells["colFkId"].Value.ToString())
                                }
                            }
                        });
                    }
                }
            }

            AbrirVentanaSeleccionCampos();
            CargarGridConsultas();
        }

        private void AbrirVentanaSeleccionCampos()
        {
            FrmCamposTabla frmCampos = new FrmCamposTabla(this);
            int indiceConsulta = listaConsultas.Count() - 1;

            frmCampos.cadenaConexion = lblstrConexion.Text;
            frmCampos.baseDatos = lblDataBase.Text;
            frmCampos.Objeto = listaConsultas;
            frmCampos.cadenaTablas = string.Join(",", listaConsultas[indiceConsulta].ListaTablasRelacionadas
                .SelectMany(tabla => tabla.ListaColumnasRelacion.Select(relacion => relacion.IdLlaveForanea))
                .Distinct()
                .ToArray()) + $",{dgvTablas.SelectedRows[0].Cells["colTab_Id"].Value.ToString()}";
            frmCampos.NombreObjeto = txtNombreObjeto.Text;
            frmCampos.ShowDialog(this);
        }

        private void AbrirVentanaSeleccionCamposFront()
        {
            if (listaConsultasFront.Count > 0)
            {
                FormCamposFront formCamposFront = new FormCamposFront(this);
                int indiceConsulta = listaConsultasFront.Count() - 1;

                formCamposFront.cadenaConexion = lblstrConexion.Text;
                formCamposFront.baseDatos = lblDataBase.Text;
                formCamposFront.cadenaTablas = string.Join(",", listaConsultasFront[indiceConsulta].ListaTablasRelacionadas
                    .SelectMany(tabla => tabla.ListaColumnasRelacion.Select(relacion => relacion.IdLlaveForanea))
                    .Distinct()
                    .ToArray());
                formCamposFront.NombreObjeto = txtNombreObjeto.Text;
                formCamposFront.ShowDialog(this);
            }
            else MessageBox.Show("Debe seleccionar una relación primero");
        }

        private void CargarGridConsultas()
        {
            List<object> listaGridConsultas = new List<object>();

            listaConsultas.ForEach(consulta =>
            {
                listaGridConsultas.Add(new { ConsultaId = listaConsultas.IndexOf(consulta), ConsultaNombre = consulta.NombreObjeto });
            });

            BindingList<object> listaEnlace = new BindingList<object>(listaGridConsultas);
            BindingSource consultas = new BindingSource(listaEnlace, null);
            dgvConsultas.DataSource = consultas;
        }

        private List<ColumnaRelacion> ObtenerColumnasRelacion(string cadenaIdsFK)
        {
            SqlCommand cmd = new SqlCommand();
            SqlDataAdapter da = new SqlDataAdapter();
            DataSet ds = new DataSet();
            List<ColumnaRelacion> listaColumnasRelacion = new List<ColumnaRelacion>();

            try
            {
                SqlConnection con = new SqlConnection(lblstrConexion.Text);
                con.Open();
                cmd.Connection = con;
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = $"Use {lblDataBase.Text} {string.Format(Recursos.RecursosBD.QueryColumnasRelacion, cadenaIdsFK)}";
                da.SelectCommand = cmd;
                da.Fill(ds);
                con.Close();

                foreach (DataRow registro in ds.Tables[0].Rows)
                {
                    listaColumnasRelacion.Add(new ColumnaRelacion
                    {
                        IdLlaveForanea = registro["FK_Id"].ToString(),
                        ColumnaOrigen = registro["ColumnaOrigen"].ToString(),
                        ColumnaDestino = registro["ColumnaRelacion"].ToString()
                    });
                }
            }
            catch (SqlException x)
            {
                MessageBox.Show("Error de SQL :" + x.Message);
            }
            catch (Exception y)
            {
                MessageBox.Show("Error :" + y.Message);
            }
            return listaColumnasRelacion;
        }

        private void dgvRelaciones_CellClick(object sender, DataGridViewCellEventArgs e)
        {
            if (e.RowIndex >= 0)
            {
                if (dgvRelaciones.Rows[e.RowIndex].Cells["colSelect"].Value == null)
                    dgvRelaciones.Rows[e.RowIndex].Cells["colSelect"].Value = true;
                else if (bool.Parse(dgvRelaciones.Rows[e.RowIndex].Cells["colSelect"].Value.ToString()) == true)
                    dgvRelaciones.Rows[e.RowIndex].Cells["colSelect"].Value = false;
                else if (bool.Parse(dgvRelaciones.Rows[e.RowIndex].Cells["colSelect"].Value.ToString()) == false)
                    dgvRelaciones.Rows[e.RowIndex].Cells["colSelect"].Value = true;
            }
        }

        private void dgvConsultas_CellContentClick(object sender, DataGridViewCellEventArgs e)
        {
            var senderGrid = (DataGridView)sender;

            if (senderGrid.Columns[e.ColumnIndex] is DataGridViewButtonColumn && e.RowIndex >= 0)
            {
                if (senderGrid.Columns[e.ColumnIndex].Name == "colConsultasbtnScript")
                {
                    colConsultasbtnScript_Click(e);
                }
            }
        }

        private void colConsultasbtnScript_Click(DataGridViewCellEventArgs e)
        {
            int indice = int.Parse(dgvConsultas.Rows[e.RowIndex].Cells["colConsultasIndice"].Value.ToString());

            FrmVisorConsulta frmVisor = new FrmVisorConsulta(this, indice);
            frmVisor.ShowDialog(this);
        }
    }
}