using TravelAgencyWinForms.Models;

namespace TravelAgencyWinForms.Services;

public static class EntityConfigs
{
    public static EntityConfig Clients => new()
    {
        Title = "Клиенты",
        TableName = "clients",
        OrderBy = "client_id",
        Fields = new()
        {
            Id("client_id", "ID"),
            Text("first_name", "Имя", true),
            Text("last_name", "Фамилия", true),
            Text("middle_name", "Отчество"),
            Text("passport_data", "Паспорт", true),
            Text("phone", "Телефон"),
            Text("email", "Email"),
            Date("registration_date", "Дата регистрации", true)
        }
    };

    public static EntityConfig Positions => new()
    {
        Title = "Должности",
        TableName = "positions",
        OrderBy = "position_id",
        Fields = new()
        {
            Id("position_id", "ID"),
            Text("name", "Название", true),
            Decimal("salary", "Зарплата", true)
        }
    };

    public static EntityConfig Employees => new()
    {
        Title = "Сотрудники",
        TableName = "employees",
        OrderBy = "employee_id",
        Fields = new()
        {
            Id("employee_id", "ID"),
            Text("first_name", "Имя", true),
            Text("last_name", "Фамилия", true),
            Text("middle_name", "Отчество"),
            Text("passport_data", "Паспорт", true),
            Text("phone", "Телефон"),
            Date("birth_date", "Дата рождения"),
            Lookup("position_id", "Должность", true,
                "SELECT position_id AS id, name FROM positions ORDER BY name", "id", "name")
        }
    };

    public static EntityConfig Cities => new()
    {
        Title = "Города",
        TableName = "cities",
        OrderBy = "city_id",
        Fields = new()
        {
            Id("city_id", "ID"),
            Text("city_name", "Название города", true)
        }
    };

    public static EntityConfig Tours => new()
    {
        Title = "Туры",
        TableName = "tours",
        OrderBy = "tour_id",
        Fields = new()
        {
            Id("tour_id", "ID"),
            Text("name", "Название тура", true),
            Decimal("price", "Стоимость", true)
        }
    };

    public static EntityConfig TourCities => new()
    {
        Title = "Города в турах",
        TableName = "tour_cities",
        OrderBy = "tour_id, city_id",
        Fields = new()
        {
            Lookup("tour_id", "Тур", true,
                "SELECT tour_id AS id, name FROM tours ORDER BY name", "id", "name", isKey: true),
            Lookup("city_id", "Город", true,
                "SELECT city_id AS id, city_name AS name FROM cities ORDER BY city_name", "id", "name", isKey: true)
        }
    };

    public static EntityConfig TourList => new()
    {
        Title = "Расписание туров",
        TableName = "tour_list",
        OrderBy = "tour_list_id",
        Fields = new()
        {
            Id("tour_list_id", "ID"),
            Lookup("tour_id", "Тур", true,
                "SELECT tour_id AS id, name FROM tours ORDER BY name", "id", "name"),
            Date("start_date", "Дата начала", true),
            Date("end_date", "Дата окончания", true)
        }
    };

    public static EntityConfig Bookings => new()
    {
        Title = "Бронирования",
        TableName = "bookings",
        OrderBy = "booking_id",
        Fields = new()
        {
            Id("booking_id", "ID"),
            Text("booking_number", "Номер бронирования", true),
            Lookup("client_id", "Клиент", true,
                "SELECT client_id AS id, concat_ws(' ', last_name, first_name, middle_name) AS name FROM clients ORDER BY last_name, first_name", "id", "name"),
            Lookup("employee_id", "Сотрудник", true,
                "SELECT employee_id AS id, concat_ws(' ', last_name, first_name, middle_name) AS name FROM employees ORDER BY last_name, first_name", "id", "name"),
            Lookup("tour_list_id", "Тур из расписания", true,
                "SELECT tour_list_id AS id, tour_name || ' (' || start_date || ' - ' || end_date || ')' AS name FROM v_tour_schedule ORDER BY start_date", "id", "name"),
            Date("booking_date", "Дата оформления", true),
            Enum("status", "Статус", true, "новая", "подтверждена", "оплачена", "отменена")
        }
    };

    public static EntityConfig AppUsers => new()
    {
        Title = "Пользователи приложения",
        TableName = "app_users",
        OrderBy = "user_id",
        Fields = new()
        {
            Id("user_id", "ID"),
            Text("login", "Логин", true),
            Password("password_hash", "Пароль", false),
            Enum("role", "Роль", true, "admin", "user"),
            Bool("is_active", "Активен", true),
            Lookup("employee_id", "Связанная запись", false,
                "SELECT employee_id AS id, concat_ws(' ', last_name, first_name, middle_name) AS name FROM employees ORDER BY last_name, first_name", "id", "name")
        }
    };

    public static EntityConfig ClientDetails => ReadOnlyView("Мои данные клиента", "clients", "client_id", true, "client_id");
    public static EntityConfig BookingDetails => ReadOnlyView("Бронирования подробно", "v_booking_details", "booking_id", false, null);
    public static EntityConfig TourScheduleView => ReadOnlyView("Расписание туров", "v_tour_schedule", "tour_list_id", false, null);
    public static EntityConfig OverdueView => ReadOnlyView("Просроченные бронирования", "v_overdue_client_bookings", "booking_id", false, null);
    public static EntityConfig AuditLog => ReadOnlyView("Журнал операций", "audit_log", "changed_at DESC", false, null);

    public static EntityConfig UserBookings => ReadOnlyView("Мои бронирования", "v_booking_details", "booking_id", true, "client_id");
    public static EntityConfig UserOverdue => ReadOnlyView("Мои просроченные бронирования", "v_overdue_client_bookings", "booking_id", true, "client_id");

    private static EntityConfig ReadOnlyView(string title, string view, string orderBy, bool restrict, string? restrictColumn)
    {
        return new EntityConfig
        {
            Title = title,
            TableName = view,
            ViewName = view,
            OrderBy = orderBy,
            ReadOnly = true,
            RestrictByCurrentEmployee = restrict,
            RestrictColumn = restrictColumn,
            Fields = new()
        };
    }

    private static FieldConfig Id(string name, string label) => new()
    {
        Name = name,
        Label = label,
        Kind = FieldKind.Integer,
        IsKey = true,
        AutoIdentity = true,
        ReadOnlyOnEdit = true
    };

    private static FieldConfig Text(string name, string label, bool required = false) => new()
    {
        Name = name,
        Label = label,
        Kind = FieldKind.Text,
        Required = required
    };

    private static FieldConfig Password(string name, string label, bool required = false) => new()
    {
        Name = name,
        Label = label,
        Kind = FieldKind.Password,
        Required = required,
        ShowInGrid = false
    };

    private static FieldConfig Decimal(string name, string label, bool required = false) => new()
    {
        Name = name,
        Label = label,
        Kind = FieldKind.Decimal,
        Required = required
    };

    private static FieldConfig Date(string name, string label, bool required = false) => new()
    {
        Name = name,
        Label = label,
        Kind = FieldKind.Date,
        Required = required
    };

    private static FieldConfig Bool(string name, string label, bool required = false) => new()
    {
        Name = name,
        Label = label,
        Kind = FieldKind.Boolean,
        Required = required
    };

    private static FieldConfig Enum(string name, string label, bool required, params string[] options) => new()
    {
        Name = name,
        Label = label,
        Kind = FieldKind.Enum,
        Required = required,
        Options = options
    };

    private static FieldConfig Lookup(
        string name,
        string label,
        bool required,
        string sql,
        string valueColumn,
        string displayColumn,
        bool isKey = false) => new()
    {
        Name = name,
        Label = label,
        Kind = FieldKind.Lookup,
        Required = required,
        LookupSql = sql,
        LookupValueColumn = valueColumn,
        LookupDisplayColumn = displayColumn,
        IsKey = isKey,
        AutoIdentity = false,
        ReadOnlyOnEdit = isKey
    };
}
