using System;
using System.Collections.Generic;
using System.Data.SqlClient;
using System.Linq;
using System.Security.Cryptography.Xml;
using System.Windows;
using System.Windows.Input;
using UI.Database;


namespace UI.Dashboard
{
    // ─────────────────────────────────────────
    // MODEL
    // ─────────────────────────────────────────
    public class PessoaViewModel
    {
        public int Id { get; set; }
        public string NomeCompleto { get; set; } = "";
        public string Email { get; set; } = "";
        public string Telefone { get; set; } = "";
        public string Cidade { get; set; } = "";
        public string Cargo { get; set; } = "";
        public DateTime? DataNascimento { get; set; }

        public string DataNascFormatada =>
            DataNascimento.HasValue ? DataNascimento.Value.ToString("dd/MM/yyyy") : "-";

        public string Iniciais
        {
            get
            {
                var p = NomeCompleto.Split(' ', StringSplitOptions.RemoveEmptyEntries);
                if (p.Length >= 2) return $"{p[0][0]}{p[^1][0]}".ToUpper();
                return NomeCompleto.Length >= 2 ? NomeCompleto[..2].ToUpper() : NomeCompleto.ToUpper();
            }
        }

        private static readonly (string Bg, string Fg)[] Paleta =
        {
            ("#1A3A6E","#60A5FA"), ("#3A1A3A","#C084FC"), ("#1A3A20","#4ADE80"),
            ("#3A2A10","#FCD34D"), ("#1A2A3A","#38BDF8"), ("#3A1A20","#FB7185"),
            ("#1A3A35","#34D399"),
        };

        public string AvatarBackground => Paleta[Math.Abs(Id) % Paleta.Length].Bg;
        public string AvatarForeground => Paleta[Math.Abs(Id) % Paleta.Length].Fg;
    }

    // ─────────────────────────────────────────
    // MODEL DA PAGINACAO
    // ─────────────────────────────────────────
    public class PaginaItem
    {
        public string Label { get; set; } = "";
        public bool IsActive { get; set; }
        public string FontWeight => IsActive ? "Bold" : "Normal";
    }

    // ─────────────────────────────────────────
    // REPOSITORIO
    // ─────────────────────────────────────────
    public class PessoaRepository
    {
        private readonly string _connectionString;

        public PessoaRepository(string connectionString)
        {
            _connectionString = connectionString;
        }

        public (List<PessoaViewModel> Itens, int TotalRegistros) Buscar(
            string filtro, int pagina, int itensPorPagina)
        {
            using var conn = new SqlConnection(_connectionString);
            conn.Open();

            var filtroParam = string.IsNullOrWhiteSpace(filtro) ? "%" : $"%{filtro}%";
            var offset = (pagina - 1) * itensPorPagina;

            int total;

            using (var cmdCount = new SqlCommand(@"
        SELECT COUNT(*) 
        FROM Pessoas
        WHERE @filtro = '%'
           OR NomeCompleto LIKE @filtro
           OR Email        LIKE @filtro
           OR Telefone     LIKE @filtro", conn))
            {
                cmdCount.Parameters.AddWithValue("@filtro", filtroParam);
                total = (int)cmdCount.ExecuteScalar();
            }

            var itens = new List<PessoaViewModel>();

            using (var cmd = new SqlCommand(@"
        SELECT Id, NomeCompleto, Email, Telefone, Cidade, Cargo, DataNascimento
        FROM Pessoas
        WHERE @filtro = '%'
           OR NomeCompleto LIKE @filtro
           OR Email        LIKE @filtro
           OR Cidade       LIKE @filtro
           OR Cargo        LIKE @filtro
        ORDER BY NomeCompleto
        OFFSET @offset ROWS FETCH NEXT @qtd ROWS ONLY", conn))
            {
                cmd.Parameters.AddWithValue("@filtro", filtroParam);
                cmd.Parameters.AddWithValue("@offset", offset);
                cmd.Parameters.AddWithValue("@qtd", itensPorPagina);

                using var reader = cmd.ExecuteReader();

                while (reader.Read())
                {
                    itens.Add(new PessoaViewModel
                    {
                        Id = reader.GetInt32(0),
                        NomeCompleto = reader.IsDBNull(1) ? "" : reader.GetString(1),
                        Email = reader.IsDBNull(2) ? "" : reader.GetString(2),
                        Telefone = reader.IsDBNull(3) ? "" : reader.GetString(3),
                        Cidade = reader.IsDBNull(4) ? "" : reader.GetString(4),
                        Cargo = reader.IsDBNull(5) ? "" : reader.GetString(5),
                        DataNascimento = reader.IsDBNull(6) ? null : reader.GetDateTime(6)
                    });
                }
            }

            return (itens, total);
        }
    }

    // ─────────────────────────────────────────
    // CODE-BEHIND
    // ─────────────────────────────────────────
    public partial class DashboardMain : Window
    {
        private PessoaRepository? _repo;
        private int _paginaAtual = 1;
        private int _itensPorPagina = 10;
        private int _totalRegistros = 0;
        private string _filtroAtual = "";

        // Controles da tabela — resolvidos via FindName no OnLoaded
        private System.Windows.Controls.Border? _loadingPanel;
        private System.Windows.Controls.Border? _emptyPanel;
        private System.Windows.Controls.ItemsControl? _listaPessoas;
        private System.Windows.Controls.ItemsControl? _paginacaoPanel;
        private System.Windows.Controls.Button? _btnAnterior;
        private System.Windows.Controls.Button? _btnProximo;
        private System.Windows.Controls.TextBlock? _runPaginaInfo;

        // ✅ Barras do gráfico de Distribuição por Sexo
        private System.Windows.Controls.Border? _barMasc;
        private System.Windows.Controls.Border? _barFem;
        private System.Windows.Controls.Border? _barOutros;

        // ─────────────────────────────────────────
        // CONSTRUTOR
        // ─────────────────────────────────────────
        public DashboardMain()
        {
            InitializeComponent();
            Loaded += OnLoaded;

            this.lblCadHoje.Text = ObterCadastrosHoje().ToString();
            this.CarregarResumo();
        }

        // ─────────────────────────────────────────
        // QUERIES — inalteradas em relação ao original
        // ─────────────────────────────────────────
        public int ObterCadastrosHoje()
        {
            using var conn = new SqlConnection(DadosConexao.ObterStringConexao());
            conn.Open();
            using var cmd = new SqlCommand(
                "SELECT TotalHoje FROM vw_CadastrosHoje", conn);
            var resultado = cmd.ExecuteScalar();
            return resultado != null ? Convert.ToInt32(resultado) : 0;
        }

        public (string total, string crescimento) ObterResumoCadastros()
        {
            using var conn = new SqlConnection(DadosConexao.ObterStringConexao());
            conn.Open();
            using var cmd = new SqlCommand(
                "SELECT TotalCadastros, CrescimentoPercentual FROM vw_ResumoCadastros", conn);
            using var reader = cmd.ExecuteReader();
            if (reader.Read())
            {
                int total = reader.GetInt32(0);
                decimal crescimento = reader.GetDecimal(1);
                return (total.ToString("N0"), $"↑ {Math.Round(crescimento)}%");
            }
            return ("0", "0%");
        }

        public (string ativos, string inativos) ObterStatusPessoas()
        {
            using var conn = new SqlConnection(DadosConexao.ObterStringConexao());
            conn.Open();
            using var cmd = new SqlCommand(
                "SELECT Ativos, Inativos FROM vw_StatusPessoas", conn);
            using var reader = cmd.ExecuteReader();
            if (reader.Read())
            {
                int ativos = reader.GetInt32(0);
                int inativos = reader.GetInt32(1);
                return (ativos.ToString("N0"), inativos.ToString("N0"));
            }
            return ("0", "0");
        }

        // ✅ Query original preservada — apenas 3 colunas, sem alterar a view
        public (string masc, string fem, string outros) ObterDistribuicaoSexo()
        {
            using var conn = new SqlConnection(DadosConexao.ObterStringConexao());
            conn.Open();
            using var cmd = new SqlCommand(
                "SELECT PercentMasculino, PercentFeminino, PercentOutros FROM vw_DistribuicaoSexo",
                conn);
            using var reader = cmd.ExecuteReader();
            if (reader.Read())
            {
                decimal masc = reader.GetDecimal(0);
                decimal fem = reader.GetDecimal(1);
                decimal outros = reader.GetDecimal(2);
                return (
                    $"{Math.Round(masc)}%",
                    $"{Math.Round(fem)}%",
                    $"{Math.Round(outros)}%"
                );
            }
            return ("0%", "0%", "0%");
        }

        // ─────────────────────────────────────────
        // CARREGA RESUMO (cards + gráfico)
        // ─────────────────────────────────────────
        private void CarregarResumo()
        {
            var resumo = ObterResumoCadastros();
            var status = ObterStatusPessoas();
            var sexo = ObterDistribuicaoSexo();

            TxtTotalCadastros.Text = resumo.total;
            TxtCrescimento.Text = resumo.crescimento;
            TxtAtivos.Text = status.ativos;
            TxtInativos.Text = status.inativos;

            // Percentuais nos TextBlocks do gráfico
            TxtMasc.Text = sexo.masc;
            TxtFem.Text = sexo.fem;
            TxtOutros.Text = sexo.outros;

            // Tenta atualizar as barras — se Loaded ainda não rodou,
            // os campos serão null e a chamada é no-op.
            // O OnLoaded chama novamente para garantir.
            AtualizarBarrasGrafico(sexo.masc, sexo.fem, sexo.outros);
        }

        // ─────────────────────────────────────────
        // GRÁFICO DE BARRAS — DISTRIBUIÇÃO POR SEXO
        // ─────────────────────────────────────────

        /// <summary>
        /// Recebe as strings de percentual ("52%", "43%", "5%")
        /// e ajusta a largura de cada barra proporcionalmente.
        /// </summary>
        private void AtualizarBarrasGrafico(string mascPct, string femPct, string outrosPct)
        {
            const double BarMaxWidth = 250; // px — ajuste se o card mudar de tamanho
            const double BarMinWidth = 4;   // evita barra invisível quando valor é 0

            double m = ParsePct(mascPct);
            double f = ParsePct(femPct);
            double o = ParsePct(outrosPct);

            // Normaliza caso a soma não seja exatamente 100
            double soma = m + f + o;
            if (soma > 0) { m = m / soma * 100; f = f / soma * 100; o = o / soma * 100; }

            if (_barMasc != null) _barMasc.Width = Math.Max(BarMinWidth, m / 100 * BarMaxWidth);
            if (_barFem != null) _barFem.Width = Math.Max(BarMinWidth, f / 100 * BarMaxWidth);
            if (_barOutros != null) _barOutros.Width = Math.Max(BarMinWidth, o / 100 * BarMaxWidth);
        }

        /// <summary>Converte "52%" → 52.0 com segurança.</summary>
        private static double ParsePct(string pct)
        {
            var limpo = pct.Replace("%", "").Replace(",", ".").Trim();
            return double.TryParse(limpo,
                System.Globalization.NumberStyles.Any,
                System.Globalization.CultureInfo.InvariantCulture,
                out double v) ? v : 0;
        }

        // ─────────────────────────────────────────
        // LOADED
        // ─────────────────────────────────────────
        private void OnLoaded(object sender, RoutedEventArgs e)
        {
            // Controles da tabela
            _loadingPanel = FindName("LoadingPanel") as System.Windows.Controls.Border;
            _emptyPanel = FindName("EmptyPanel") as System.Windows.Controls.Border;
            _listaPessoas = FindName("ListaPessoas") as System.Windows.Controls.ItemsControl;
            _paginacaoPanel = FindName("PaginacaoPanel") as System.Windows.Controls.ItemsControl;
            _btnAnterior = FindName("BtnAnterior") as System.Windows.Controls.Button;
            _btnProximo = FindName("BtnProximo") as System.Windows.Controls.Button;
            _runPaginaInfo = FindName("RunPaginaInfo") as System.Windows.Controls.TextBlock;

            // ✅ Barras do gráfico
            _barMasc = FindName("BarMasc") as System.Windows.Controls.Border;
            _barFem = FindName("BarFem") as System.Windows.Controls.Border;
            _barOutros = FindName("BarOutros") as System.Windows.Controls.Border;

            // Aplica as barras agora que os controles estão resolvidos
            AtualizarBarrasGrafico(TxtMasc.Text, TxtFem.Text, TxtOutros.Text);

            // Inicializa repositório e carrega a tabela
            try
            {
                string conexao = DadosConexao.ObterStringConexao();
                if (string.IsNullOrWhiteSpace(conexao))
                {
                    MessageBox.Show(
                        "String de conexão não configurada.\nVerifique DadosConexao.ObterStringConexao().",
                        "Configuração", MessageBoxButton.OK, MessageBoxImage.Warning);
                    return;
                }
                _repo = new PessoaRepository(conexao);
                CarregarPessoas();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Erro ao inicializar conexão:\n{ex.Message}",
                    "Erro", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        // ─────────────────────────────────────────
        // JANELA
        // ─────────────────────────────────────────
        private void Window_MouseDown(object sender, MouseButtonEventArgs e)
        {
            if (e.ChangedButton == MouseButton.Left) DragMove();
        }

        private void BtnFechar_Click(object sender, RoutedEventArgs e)
        {
            Application.Current.Shutdown();
        }

        // ─────────────────────────────────────────
        // TABELA / PAGINAÇÃO
        // ─────────────────────────────────────────
        private void CarregarPessoas()
        {
            if (_repo == null) return;

            if (_loadingPanel != null) _loadingPanel.Visibility = Visibility.Visible;
            if (_emptyPanel != null) _emptyPanel.Visibility = Visibility.Collapsed;
            if (_listaPessoas != null) _listaPessoas.ItemsSource = null;

            try
            {
                var (itens, total) = _repo.Buscar(_filtroAtual, _paginaAtual, _itensPorPagina);
                _totalRegistros = total;

                if (itens.Count == 0)
                {
                    if (_emptyPanel != null) _emptyPanel.Visibility = Visibility.Visible;
                }
                else
                {
                    if (_listaPessoas != null) _listaPessoas.ItemsSource = itens;
                }

                AtualizarPaginacao();
                AtualizarInfoRegistros();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Erro ao carregar pessoas:\n{ex.Message}",
                    "Erro", MessageBoxButton.OK, MessageBoxImage.Error);
            }
            finally
            {
                if (_loadingPanel != null) _loadingPanel.Visibility = Visibility.Collapsed;
            }
        }

        private void AtualizarPaginacao()
        {
            int totalPaginas = (int)Math.Ceiling(_totalRegistros / (double)_itensPorPagina);
            if (totalPaginas < 1) totalPaginas = 1;

            int inicio = Math.Max(1, _paginaAtual - 2);
            int fim = Math.Min(totalPaginas, inicio + 4);
            inicio = Math.Max(1, fim - 4);

            var paginas = new List<PaginaItem>();

            if (inicio > 1)
                paginas.Add(new PaginaItem { Label = "..." });

            for (int i = inicio; i <= fim; i++)
                paginas.Add(new PaginaItem { Label = i.ToString(), IsActive = i == _paginaAtual });

            if (fim < totalPaginas)
                paginas.Add(new PaginaItem { Label = "..." });

            if (_paginacaoPanel != null) _paginacaoPanel.ItemsSource = paginas;
            if (_btnAnterior != null) _btnAnterior.IsEnabled = _paginaAtual > 1;
            if (_btnProximo != null) _btnProximo.IsEnabled = _paginaAtual < totalPaginas;
        }

        private void AtualizarInfoRegistros()
        {
            if (_runPaginaInfo == null) return;

            int ini = (_paginaAtual - 1) * _itensPorPagina + 1;
            int fim = Math.Min(_paginaAtual * _itensPorPagina, _totalRegistros);

            _runPaginaInfo.Text = _totalRegistros == 0
                ? "0 registros"
                : $"{ini}-{fim} de {_totalRegistros:N0}";
        }

        private void BtnAnterior_Click(object sender, RoutedEventArgs e)
        {
            if (_paginaAtual > 1) { _paginaAtual--; CarregarPessoas(); }
        }

        private void BtnProximo_Click(object sender, RoutedEventArgs e)
        {
            int totalPaginas = (int)Math.Ceiling(_totalRegistros / (double)_itensPorPagina);
            if (_paginaAtual < totalPaginas) { _paginaAtual++; CarregarPessoas(); }
        }

        private void CmbItensPorPagina_SelectionChanged(object sender,
            System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (CmbItensPorPagina?.SelectedItem is System.Windows.Controls.ComboBoxItem item
                && int.TryParse(item.Content?.ToString(), out int qtd))
            {
                _itensPorPagina = qtd;
                _paginaAtual = 1;
                CarregarPessoas();
            }
        }

        private void BtnNovoCadastro_Click(object sender, RoutedEventArgs e)
        {
            var cp = new UI.Cadastro.FrmCadastroClientes();
            cp.ShowDialog();
        }
    }
}
