import { _documents, _genFile } from "src/_mock"

export type FileFormat =
    | 'pdf'
    | 'docx'
    | 'xlsx'
    | 'csv'
    | 'pptx'
    | 'txt'
    | 'json'
    | 'xml'
    | 'html'
    | 'jpg'
    | 'png'
    | 'svg'
    | 'zip'
    | 'md';

const validExtensions: FileFormat[] = [
    'pdf', 'docx', 'xlsx', 'csv', 'pptx',
    'txt', 'json', 'xml', 'html', 'jpg',
    'png', 'svg', 'zip', 'md'
];

type DocAttribute = {
    name: string;
    serilizedValue: string;
}

export class Doc {

    static map(source?: Partial<Doc>): Doc {
        const doc = new Doc();
        Object.assign(doc, source);
        return doc;
    }

    id!: number;
    name!: string;
    addedWhen!: Date;
    addedWho!: string;
    changedWhen?: Date;
    changedWho?: string;
    attributes: Array<DocAttribute> = [];

    get data(): Promise<Uint8Array> {
        return Promise.resolve(_genFile(this.name)!);
    }

    getChangedInfo(separator: string = " | "): string | null {
        const who = this.changedWho?.trim();
        const when = this.changedWhen?.toLocaleDateString('de-DE');

        if (!who && !when) {
            return null;
        }

        return [who, when].filter(Boolean).join(separator);
    }

    get extension(): FileFormat {
        const parts = this.name.split('.');
        if (parts.length > 1 && parts[parts.length - 1].trim() !== '') {
            const ext = parts[parts.length - 1].toLowerCase();

            if (validExtensions.includes(ext as FileFormat))
                return ext as FileFormat;
        }
        throw new Error(`Invalid or missing file extension in filename: "${this.name}". Supported extensions are: ${validExtensions.join(', ')}.`);
    }

    get iconSrc(): string {
        return `assets/icons/file/${this.extension ?? 'unknown'}.svg`;
    }
}

export type DocQuery = {
    id?: number | undefined,
    name?: string | undefined,
    attributes?: Record<string, string>
}

class DocService {
    get(query: DocQuery | undefined = undefined): Promise<Doc[]> {
        let documents = _documents;

        if (query?.id)
            documents = documents.filter(d => d.id === query.id);

        if (query?.name)
            documents = documents.filter(d => d.name === query.name);

        for (const name in query?.attributes) {
            const attr = query.attributes[name];
            documents = documents.filter(d => d.attributes.find(a => a.name === name)?.serilizedValue.toLowerCase().includes(attr.toLowerCase()));
        }

        return Promise.resolve(documents);
    }

    getById(id: number): Promise<Doc[]> {
        return this.get({ id: id });
    }

    getByName(name: string): Promise<Doc[]> {
        return this.get({ name: name });
    }

    getByAttribute(attributes: Record<string, string>): Promise<Doc[]> {
        return this.get({ attributes: attributes });
    }
}

export default new DocService();