import { Address, Company, Identifiable, Internship, Mentor, Office, Student } from "@/data";
import { momentSerializationTransformer, OneWayTransformer, Transformer } from "@/serialization";
import { Nullable } from "@/helpers";
import { MentorDTO, mentorDtoTransformer } from "@/api/dto/mentor";
import { InternshipTypeDTO, internshipTypeDtoTransformer } from "@/api/dto/type";
import { Moment } from "moment-timezone";
import { sampleStudent } from "@/provider/dummy";
import { UploadType } from "@/api/upload";
import { ProgramEntryDTO, programEntryDtoTransformer } from "@/api/dto/edition";
import { StudentDTO } from "@/api/dto/student";
import { SubmissionStatus } from "@/state/reducer/submission";

export enum SubmissionState {
    Draft = "Draft",
    Submitted = "Submitted",
    Accepted = "Accepted",
    Rejected = "Rejected",
    Archival = "Archival",
}

export const submissionStateDtoTransformer: Transformer<SubmissionState, SubmissionStatus> = {
    reverseTransform(subject: SubmissionStatus, context: undefined): SubmissionState {
        switch (subject) {
            case "draft":
                return SubmissionState.Draft;
            case "awaiting":
                return SubmissionState.Submitted;
            case "accepted":
                return SubmissionState.Accepted;
            case "declined":
                return SubmissionState.Rejected;
        }
    },
    transform(subject: SubmissionState, context: undefined): SubmissionStatus {
        switch (subject) {
            case SubmissionState.Draft:
                return "draft";
            case SubmissionState.Submitted:
                return "awaiting";
            case SubmissionState.Accepted:
                return "accepted";
            case SubmissionState.Rejected:
                return "declined";
            case SubmissionState.Archival:
                return "declined";
        }
    }
}

export interface NewBranchOffice extends Address {
}

export interface InternshipRegistrationUpdateCompany {
    id: string,
    branchOffice: Identifiable | NewBranchOffice,
}

export interface NewCompany {
    nip: string;
    name: string;
    branchOffice: NewBranchOffice | null;
}

export interface InternshipRegistrationUpdate {
    company: InternshipRegistrationUpdateCompany | NewCompany,
    start: string,
    end: string,
    type: number,
    mentor: MentorDTO,
    hours: number,
    subjects: string[],
}

export interface InternshipRegistrationDTO extends Identifiable {
    start: string;
    end: string;
    type: InternshipTypeDTO,
    state: SubmissionState,
    mentor: MentorDTO,
    company: Company,
    branchAddress: Office,
    declaredHours: number,
    subjects: { subject: ProgramEntryDTO }[],
    submissionDate: string,
}

export interface InternshipDocument extends Identifiable {
    description: null,
    type: UploadType,
    state: SubmissionState,
}

const reference = (subject: Identifiable | null): Identifiable | null => subject && { id: subject.id };

export interface InternshipInfoDTO extends Identifiable {
    internshipRegistration: InternshipRegistrationDTO;
    documentation: InternshipDocument[],
    student: StudentDTO,
}

export const internshipRegistrationUpdateTransformer: OneWayTransformer<Nullable<Internship>, Nullable<InternshipRegistrationUpdate>> = {
    transform(subject: Nullable<Internship>, context?: unknown): Nullable<InternshipRegistrationUpdate> {
        return {
            start: momentSerializationTransformer.transform(subject?.startDate) || null,
            end: momentSerializationTransformer.transform(subject?.endDate) || null,
            type: parseInt(subject?.type?.id || "0"),
            mentor: mentorDtoTransformer.reverseTransform(subject.mentor as Mentor),
            company: subject?.company?.id ? {
                id: subject?.company?.id as string,
                branchOffice: subject?.office?.id
                    ? reference(subject?.office) as Identifiable
                    : subject?.office?.address as NewBranchOffice,
            } : {
                name: subject?.company?.name as string,
                nip: subject?.company?.nip as string,
                branchOffice: subject?.office?.address as NewBranchOffice
            },
            hours: subject?.hours,
            subjects: subject?.program?.map(program => program.id as string) || [],
        }
    }
}

export const internshipRegistrationDtoTransformer: OneWayTransformer<InternshipRegistrationDTO, Internship> = {
    transform(dto: InternshipRegistrationDTO, context?: unknown): Internship {
        return {
            id: dto.id,
            office: dto.branchAddress,
            company: dto.company,
            mentor: mentorDtoTransformer.transform(dto.mentor),
            startDate: momentSerializationTransformer.reverseTransform(dto.start) as Moment,
            endDate: momentSerializationTransformer.reverseTransform(dto.end) as Moment,
            type: internshipTypeDtoTransformer.transform(dto.type),
            hours: dto.declaredHours,
            isAccepted: dto.state === SubmissionState.Accepted,
            lengthInWeeks: 0,
            program: dto.subjects.map(subject => programEntryDtoTransformer.transform(subject.subject)),
            intern: sampleStudent, // fixme
        };
    }
}