using System.Text;
using FrymasterBadgeApp.Services;
using Microsoft.Data.SqlClient;

namespace FrymasterBadgeApp;

public partial class EmployeeFormPage : ContentPage
{
    private readonly SqlService _db;
    private readonly Dictionary<string, object>? _existingEmployee;
    public Action<Dictionary<string, object>> OnSavedCallback { get; set; }
    private readonly bool _isEditMode;
    private string _tempCapturePath = "";
    private double _editX = 0;
    private double _editY = 0;
    private readonly string _photosBasePath;

    public bool IsSaved { get; private set; } = false;
    public Dictionary<string, object>? SavedEmployee { get; private set; }

    public EmployeeFormPage(SqlService db, Dictionary<string, object>? employee = null)
    {
        InitializeComponent();

        _db = db;
        _existingEmployee = employee;
        _isEditMode = employee != null;
        _photosBasePath = Preferences.Default.Get("PhotoBasePath", @"C:\FrymasterData\photos");

        EditorPhotoPreview.SetBinding(
            Image.ScaleProperty,
            new Binding("Value", source: ZoomSlider)
        );

        if (_isEditMode)
            SetupEditMode(employee!);
        else
            SetupAddMode();
    }

    private void SetupEditMode(Dictionary<string, object> employee)
    {
        TitleLabel.Text = "Edit Employee";
        SaveButton.Text = "Update";
        BadgeFetchButton.Text = "Update Badge";

        Data1Entry.Text = employee.GetValueOrDefault("Data1")?.ToString() ?? "";
        Data1Entry.IsEnabled = false;
        Data2Entry.Text = employee.GetValueOrDefault("Data2")?.ToString() ?? "";
        Data3Entry.Text = employee.GetValueOrDefault("Data3")?.ToString() ?? "";
        LastNameEntry.Text = employee.GetValueOrDefault("LastName")?.ToString() ?? "";
        Data4Entry.Text = employee.GetValueOrDefault("Data4")?.ToString() ?? "";
        Data9Entry.Text = employee.GetValueOrDefault("Data9")?.ToString() ?? "";

        if (
            DateTime.TryParse(employee.GetValueOrDefault("Data5")?.ToString(), out DateTime dateVal)
        )
            Data5DatePicker.Date = dateVal;

        MedicalCheckBox.IsChecked =
            (employee.GetValueOrDefault("Data7")?.ToString() ?? "False") == "True";
        EmsCheckBox.IsChecked = (employee.GetValueOrDefault("Data8")?.ToString() ?? "0") == "1";
        ActiveCheckBox.IsChecked =
            (employee.GetValueOrDefault("Active")?.ToString()?.ToUpper() ?? "NO") == "YES";

        string picCode = employee.GetValueOrDefault("picCode")?.ToString() ?? "";
        string photoPath = Path.Combine(_photosBasePath, $"{picCode}.jpg");

        if (File.Exists(photoPath))
        {
            EditorPhotoPreview.Source = ImageSource.FromFile(photoPath);
            _editX = SafeToDouble(employee.GetValueOrDefault("cropX"), 0.0);
            _editY = SafeToDouble(employee.GetValueOrDefault("cropY"), 0.0);
            EditorPhotoPreview.TranslationX = _editX;
            EditorPhotoPreview.TranslationY = _editY;
            ZoomSlider.Value = SafeToDouble(employee.GetValueOrDefault("cropScale"), 1.0);
        }
    }

    private void SetupAddMode()
    {
        TitleLabel.Text = "Add Employee";
        Data1Entry.Text = "";
        Data5DatePicker.Date = DateTime.Today;
        ActiveCheckBox.IsChecked = true;
    }

    private async void OnTakePhotoClicked(object sender, EventArgs e)
    {
        try
        {
            var photo = await MediaPicker.Default.CapturePhotoAsync();
            if (photo == null)
                return;
            _tempCapturePath = Path.Combine(FileSystem.CacheDirectory, "temp_form_capture.jpg");
            using (var source = await photo.OpenReadAsync())
            using (var destination = File.OpenWrite(_tempCapturePath))
                await source.CopyToAsync(destination);

            EditorPhotoPreview.Source = ImageSource.FromFile(_tempCapturePath);
            _editX = _editY = 0;
            EditorPhotoPreview.TranslationX = 0;
            EditorPhotoPreview.TranslationY = 0;
            ZoomSlider.Value = 1;
        }
        catch (Exception ex)
        {
            await DisplayAlert("Error", ex.Message, "OK");
        }
    }

    private void OnPanUpdated(object sender, PanUpdatedEventArgs e)
    {
        if (e.StatusType == GestureStatus.Running)
        {
            EditorPhotoPreview.TranslationX = _editX + e.TotalX;
            EditorPhotoPreview.TranslationY = _editY + e.TotalY;
        }
        else if (e.StatusType == GestureStatus.Completed)
        {
            _editX = EditorPhotoPreview.TranslationX;
            _editY = EditorPhotoPreview.TranslationY;
        }
    }

    private async void OnFetchBadgeClicked(object sender, EventArgs e)
    {
        Data9Entry.Text = await GenerateUniqueBadgeNumberAsync();
    }

    private async void OnSaveClicked(object sender, EventArgs e)
    {
        if (string.IsNullOrWhiteSpace(Data2Entry.Text))
            return;

        try
        {
            string recordNum = Data1Entry.Text.Trim();
            string picCode = _existingEmployee?.GetValueOrDefault("picCode")?.ToString() ?? "";

            if (!string.IsNullOrEmpty(_tempCapturePath))
            {
                picCode = $"{recordNum}_{DateTime.Now.Ticks}";
                File.Copy(_tempCapturePath, Path.Combine(_photosBasePath, $"{picCode}.jpg"), true);
            }

            var parameters = new List<SqlParameter>
            {
                new SqlParameter("@Data1", recordNum),
                new SqlParameter("@Data2", Data2Entry.Text),
                new SqlParameter("@Data3", Data3Entry.Text ?? ""),
                new SqlParameter("@LastName", LastNameEntry.Text ?? ""),
                new SqlParameter("@Data4", Data4Entry.Text ?? ""),
                new SqlParameter("@Data5", Data5DatePicker.Date),
                new SqlParameter("@Data9", Data9Entry.Text ?? ""),
                new SqlParameter("@Data7", MedicalCheckBox.IsChecked ? "True" : "False"),
                new SqlParameter("@Data8", EmsCheckBox.IsChecked ? "1" : "0"),
                new SqlParameter("@Active", ActiveCheckBox.IsChecked ? "YES" : "NO"),
                new SqlParameter("@picCode", picCode),
                new SqlParameter("@cropX", EditorPhotoPreview.TranslationX),
                new SqlParameter("@cropY", EditorPhotoPreview.TranslationY),
                new SqlParameter("@cropScale", ZoomSlider.Value),
            };

            string sql = _isEditMode
                ? "UPDATE dbo.tblData SET Data1=@Data1, Data2=@Data2, Data3=@Data3, LastName=@LastName, Data4=@Data4, Data5=@Data5, Data9=@Data9, Data7=@Data7, Data8=@Data8, Active=@Active, picCode=@picCode, cropX=@cropX, cropY=@cropY, cropScale=@cropScale WHERE Data1=@Data1"
                : "INSERT INTO dbo.tblData (Data1, Data2, Data3, LastName, Data4, Data5, Data9, Data7, Data8, Active, picCode, cropX, cropY, cropScale, BadgeType, ToPrint, CdsPrinted) VALUES (@Data1, @Data2, @Data3, @LastName, @Data4, @Data5, @Data9, @Data7, @Data8, @Active, @picCode, @cropX, @cropY, @cropScale, 'Office', 0, 0)";

            _db.Execute(sql, parameters.ToArray());
            try
            {
                // After successful DB execution:
                var savedData = new Dictionary<string, object>
                {
                    { "Data1", recordNum },
                    { "Data2", Data2Entry.Text },
                };

                // Trigger the callback before closing
                OnSavedCallback?.Invoke(savedData);

                await Navigation.PopModalAsync();
            }
            catch (Exception ex)
            {
                await DisplayAlert("Error", ex.Message, "OK");
            }
            IsSaved = true;
            await Navigation.PopModalAsync();
        }
        catch (Exception ex)
        {
            await DisplayAlert("Save Error", ex.Message, "OK");
        }
    }

    private async Task<string> GenerateUniqueBadgeNumberAsync()
    {
        return $"*$F{Random.Shared.Next(100000, 999999)}$A*";
    }

    private string GenerateNextRecordNumber()
    {
        var result = _db.Query(
                "SELECT MAX(CAST(Data1 AS INT)) FROM dbo.tblData WHERE ISNUMERIC(Data1) = 1",
                null
            )
            .FirstOrDefault();
        return (
            result != null ? (int.Parse(result.Values.First().ToString()) + 1) : 100001
        ).ToString();
    }

    private double SafeToDouble(object? val, double defaultVal) =>
        val != null && double.TryParse(val.ToString(), out double res) ? res : defaultVal;

    private async void OnCancelClicked(object sender, EventArgs e) =>
        await Navigation.PopModalAsync();
}
