import { isNull } from "../../helpers/IsNull";
import CompaniesList from "../Companies/Companies";
import ServiceList from "../Services/Service";
import {
    PublicServicesResults,
    PublicServiceView,
    SERVICE_PUBLISHED_STATUS,
} from "../Services/Service.Interface";
import getHeader from "../../helpers/getHeader";
import { joinStrings } from "../../helpers/String";
import { AppointmentEventByClient } from "../Appointments/Appointments.Interface";
import AppointmentList from "../Appointments/Appointments";
import ClientsList from "../Clients/Clients";
import { BotEventParams, BotView } from "../WapServer/WapServer.Interface";
import WapServerList from "../WapServer/WapServer";
import { COMPANY_PUBLISHED_STATUS } from "../Companies/Companies.Interface";

export type HomeView = {
    education: PublicServicesResults;
    health: PublicServicesResults;
    economy: PublicServicesResults;
    construction: PublicServicesResults;
    other: PublicServicesResults;
};

export type UserAppointmentViewParams = {
    appointmentId: string;
    sessionUser: string;
};

export type UserAppointmentView = {
    appointment: AppointmentEventByClient;
    organization: PublicOrganizationView;
};

export type PublicOrganizationViewParams = {
    companyId: string;
};

export type PublicOrganizationView = {
    id: string;
    headerFile: string;
    headerColor: string;
    headerFontColor: string;
    headerFontShadowColor: string;
    iconFile: string;
    logoFile: string;
    categoryId: number;
    name: string;
    description: string;
    services: PublicServicesResults;
    employees: PublicServicesResults;
    address: string;
    phone: string;
    latitude: number;
    longitude: number;
    appointmentAlert: string;
};

export type PublicOrganizationServiceViewParams = {
    serviceId: string;
};

export interface PublicOrganizationServiceView {
    service: PublicServiceView;
    organization: PublicOrganizationView;
}

class Views {
    constructor() {}

    public async userAppointmentView(
        data: UserAppointmentViewParams
    ): Promise<UserAppointmentView> {
        let returnValue: UserAppointmentView = {
            appointment: {} as AppointmentEventByClient,
            organization: {} as PublicOrganizationView,
        };

        const appointments = await AppointmentList.findAppointmentsAdminByClient({
            _id: data.appointmentId,
        });

        if (appointments.events.length === 0) {
            throw new Error("La cita no existe");
        }

        returnValue.appointment = appointments.events[0];

        const client = await ClientsList.clients.findOne({ _id: returnValue.appointment.clientId });

        if (!client) {
            throw new Error("El cliente no existe");
        }

        if (String(client.userId) !== data.sessionUser) {
            throw new Error("No tienes permiso para ver esta cita");
        }

        const organization = await this.organizationView({
            companyId: String(client.companyId),
        });

        if (!organization) {
            throw new Error("La organización no existe");
        }

        returnValue.organization = organization;

        return returnValue;
    }

    public async organizationView(
        data: PublicOrganizationViewParams
    ): Promise<PublicOrganizationView> {
        const filterData =
            data.companyId.indexOf("-") >= 0 ? { slug: data.companyId } : { _id: data.companyId };

        const company = await CompaniesList.companies.findOne({
            ...filterData,
            ...{ published: COMPANY_PUBLISHED_STATUS.PUBLISHED, banned: { $ne: true } },
        });

        //TODO: chequear si es el dueño. y si esta aceptado

        if (!company) {
            throw new Error("La compañia no existe");
        }

        const services = await ServiceList.publicServices({
            page: 1,
            limit: 10,
            companyId: String(company._id),
            published: SERVICE_PUBLISHED_STATUS.PUBLISHED,
        });

        const defColor = "#" + String(process.env.DEFAULT_HEADER_COLOR);
        const defFontColor = "#" + String(process.env.DEFAULT_HEADER_FONT_COLOR);
        const defFontShadowColor = "#" + String(process.env.DEFAULT_HEADER_FONT_SHADOW_COLOR);

        return {
            id: isNull<string>(company.id, ""),
            name: isNull<string>(company.name, ""),
            description: isNull<string>(company.description, ""),
            categoryId: isNull<number>(company.categoryId, 50000),
            headerFile: getHeader(
                company.id,
                isNull<string>(company.headerFile, ""),
                ""
            ),
            headerColor: isNull<string>(company.headerColor, defColor),
            headerFontColor: isNull<string>(company.headerFontColor, defFontColor),
            headerFontShadowColor: isNull<string>(
                company.headerFontShadowColor,
                defFontShadowColor
            ),
            iconFile: isNull<string>(company.iconFile, ""),
            logoFile: isNull<string>(company.logoFile, ""),
            address: joinStrings([company.street, company.streetNumber], " "),
            phone: joinStrings([company.phoneAreaCode, company.phoneNumber], " "),
            latitude: isNull<number>(company.latitude, 0),
            longitude: isNull<number>(company.longitude, 0),
            services,
            employees: services,
            appointmentAlert: isNull<string>(company.appointmentAlert, ""),
        };
    }

    public async homeView(): Promise<HomeView> {
        const limit = 10;

        const education = await ServiceList.publicServices({
            page: 1,
            limit: limit,
            categoryId: 200,
            published: SERVICE_PUBLISHED_STATUS.PUBLISHED,
        });

        const health = await ServiceList.publicServices({
            page: 1,
            limit: limit,
            categoryId: 100,
            published: SERVICE_PUBLISHED_STATUS.PUBLISHED,
        });

        const economy = await ServiceList.publicServices({
            page: 1,
            limit: limit,
            categoryId: 300,
            published: SERVICE_PUBLISHED_STATUS.PUBLISHED,
        });

        const construction = await ServiceList.publicServices({
            page: 1,
            limit: limit,
            categoryId: 400,
            published: SERVICE_PUBLISHED_STATUS.PUBLISHED,
        });

        const other = await ServiceList.publicServices({
            page: 1,
            limit: limit,
            categoryId: 50000,
            published: SERVICE_PUBLISHED_STATUS.PUBLISHED,
        });

        return {
            education,
            health,
            economy,
            construction,
            other,
        };
    }

    public async organizationServiceView(
        data: PublicOrganizationServiceViewParams
    ): Promise<PublicOrganizationServiceView> {
        const services = await ServiceList.publicServices({
            page: 1,
            limit: 10,
            serviceId: data.serviceId,
            published: SERVICE_PUBLISHED_STATUS.PUBLISHED,
        });

        if (services.data.length === 0) {
            throw new Error("El servicio no existe");
        }

        const service = services.data[0];

        const organization = await this.organizationView({
            companyId: String(service.organizationId),
        });

        if (!organization) {
            throw new Error("La organización no existe");
        }

        return {
            service,
            organization,
        };
    }

    public async wapView(data: BotEventParams): Promise<BotView> {
        return await WapServerList.botView(data);
    }
}

const views = new Views();

export default views;
