using System;
using System.Collections.Generic;
using System.IO;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace CarMaintenanceAppointment
{
    public partial class AppointmentForm : Form
    {
        public AppointmentForm()
        {
            InitializeComponent();
        }

        private void btnPrefill_Click(object sender, EventArgs e)
        {
            // Pre-fill the form with some valid data
            txtCustomerName.Text = "John Doe";
            txtAddress.Text = "123 Main St";
            txtCity.Text = "Toronto";
            txtProvince.Text = "ON";
            txtPostalCode.Text = "A1A 1A1";
            txtEmail.Text = "johndoe@example.com";
            txtHomePhone.Text = "123-456-7890";
            txtCellPhone.Text = "987-654-3210";
            txtMakeModel.Text = "Toyota Camry";
            txtYear.Text = "2019";
            dtpAppointmentDate.Value = DateTime.Now;
        }

        private void btnBookAppointment_Click(object sender, EventArgs e)
        {
            // Reset error label
            lblErrors.Text = "";

            // Validate input fields
            List<string> errors = new List<string>();

            // Validation rules
            if (string.IsNullOrWhiteSpace(txtCustomerName.Text))
                errors.Add("Customer name is required.");
            if (string.IsNullOrWhiteSpace(txtEmail.Text) && string.IsNullOrWhiteSpace(txtAddress.Text) && string.IsNullOrWhiteSpace(txtCity.Text) && string.IsNullOrWhiteSpace(txtProvince.Text) && string.IsNullOrWhiteSpace(txtPostalCode.Text))
                errors.Add("Postal information is required if email is not provided.");
            if (!string.IsNullOrWhiteSpace(txtProvince.Text) && (txtProvince.Text.Length != 2 || !ValidationHelper.IsValidProvinceCode(txtProvince.Text)))
                errors.Add("Province code is invalid.");
            if (!string.IsNullOrWhiteSpace(txtPostalCode.Text) && !ValidationHelper.IsValidPostalCode(txtPostalCode.Text))
                errors.Add("Postal code is invalid.");
            if (string.IsNullOrWhiteSpace(txtHomePhone.Text) && string.IsNullOrWhiteSpace(txtCellPhone.Text))
                errors.Add("Either home or cell phone must be provided.");
            if (!string.IsNullOrWhiteSpace(txtEmail.Text) && !IsValidEmail(txtEmail.Text))
                errors.Add("Email is invalid.");
            if (string.IsNullOrWhiteSpace(txtMakeModel.Text))
                errors.Add("Make & model is required.");
            if (!string.IsNullOrWhiteSpace(txtYear.Text) && (!int.TryParse(txtYear.Text, out int year) || year < 1900 || year > DateTime.Now.Year + 1))
                errors.Add("Year is invalid.");
            if (dtpAppointmentDate.Value.Date < DateTime.Today)
                errors.Add("Appointment date cannot be in the past.");

            // Display errors if any
            if (errors.Count > 0)
            {
                lblErrors.ForeColor = System.Drawing.Color.Red;
                lblErrors.Text = string.Join("\n", errors);
                FocusFirstErrorControl();
                return;
            }

            // Format and save appointment data to file
            string appointmentData = $"{ValidationHelper.Capitalize(txtCustomerName.Text)}|{ValidationHelper.Capitalize(txtAddress.Text)}|{ValidationHelper.Capitalize(txtCity.Text)}|{txtProvince.Text.ToUpper()}|{FormatPostalCode(txtPostalCode.Text)}|{txtEmail.Text.ToLower()}|{FormatPhoneNumber(txtHomePhone.Text)}|{FormatPhoneNumber(txtCellPhone.Text)}|{ValidationHelper.Capitalize(txtMakeModel.Text)}|{txtYear.Text}|{dtpAppointmentDate.Value.ToString("yyyy-MM-dd")}";

            try
            {
                using (StreamWriter writer = new StreamWriter("appointments.txt", true))
                {
                    writer.WriteLine(appointmentData);
                }
                MessageBox.Show("Appointment booked successfully!", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
                ResetForm();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"An error occurred while saving the appointment: {ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private void btnReset_Click(object sender, EventArgs e)
        {
            // Reset the form
            ResetForm();
        }

        private void btnClose_Click(object sender, EventArgs e)
        {
            // Close the form
            Close();
        }

        private bool IsValidEmail(string email)
        {
            try
            {
                var addr = new System.Net.Mail.MailAddress(email);
                return addr.Address == email;
            }
            catch
            {
                return false;
            }
        }

        private void FocusFirstErrorControl()
        {
            // Set focus to the first control with an error
            foreach (Control control in this.Controls)
            {
                if (control.GetType() == typeof(TextBox) && !string.IsNullOrEmpty(control.Text))
                {
                    control.Focus();
                    return;
                }
            }
        }

        private string FormatPostalCode(string postalCode)
        {
            // Format postal code with a single space
            return postalCode.ToUpper().Trim().Insert(3, " ");
        }

        private string FormatPhoneNumber(string phoneNumber)
        {
            // Format phone number with dashes
            return Regex.Replace(phoneNumber, @"(\d{3})(\d{3})(\d{4})", "$1-$2-$3");
        }

        private void ResetForm()
        {
            // Reset the form to its original state
            txtCustomerName.Text = "";
            txtAddress.Text = "";
            txtCity.Text = "";
            txtProvince.Text = "";
            txtPostalCode.Text = "";
            txtEmail.Text = "";
            txtHomePhone.Text = "";
            txtCellPhone.Text = "";
            txtMakeModel.Text = "";
            txtYear.Text = "";
            dtpAppointmentDate.Value = DateTime.Now;
            lblErrors.Text = "";
        }
    }

    public static class ValidationHelper
    {
        public static string Capitalize(string input)
        {
            if (string.IsNullOrEmpty(input))
                return string.Empty;

            string[] words = input.Trim().ToLower().Split(' ');
            for (int i = 0; i < words.Length; i++)
            {
                if (words[i].Length > 1)
                {
                    words[i] = char.ToUpper(words[i][0]) + words[i][1..];
                }
                else if (words[i].Length == 1)
                {
                    if (i == 0)
                        words[i] = char.ToUpper(words[i][0]).ToString();
                    else
                        words[i] = words[i].ToString();
                }
            }
            return string.Join(" ", words);
        }

        public static bool IsValidProvinceCode(string provinceCode)
        {
            if (string.IsNullOrEmpty(provinceCode))
                return false;

            // Array of valid Canadian province codes
            string[] validCodes = { "AB", "BC", "MB", "NB", "NL", "NS", "NT", "NU", "ON", "PE", "QC", "SK", "YT" };
            return Array.Exists(validCodes, code => code.Equals(provinceCode, StringComparison.OrdinalIgnoreCase));
        }

        public static bool IsValidPostalCode(string postalCode)
        {
            if (string.IsNullOrEmpty(postalCode))
                return false;

            // Regular expression to match Canadian postal code pattern
            Regex regex = new Regex(@"^[a-zA-Z]\d[a-zA-Z] ?\d[a-zA-Z]\d$");
            return regex.IsMatch(postalCode);
        }
    }
}