import { Injectable } from '@nestjs/common'
import { PrismaService } from '../prisma/prisma.service'
import { CreateHeaderDto } from './dto/create-header.dto'
import { UpdateHeaderDto } from './dto/update-header.dto'
import { CreateDetailDto } from './dto/create-detail.dto'
import { UpdateDetailDto } from './dto/update-detail.dto'
import { BootstrapTableRequestDto } from '../commons/dto/bootstrap-table-request.dto'
import { BootstrapTableResponseDto } from '../commons/dto/bootstrap-table-response.dto'
import { Prisma } from 'generated/prisma/client'
import { buildWhereClause } from 'src/commons/utils/prisma-query-builder'

@Injectable()
export class SettingsService {
    constructor(private prisma: PrismaService) { }

    // ================= HEADER =================

    createHeader(data: CreateHeaderDto) {
        return this.prisma.headerSetting.create({ data })
    }

    async findAllHeaders(query: BootstrapTableRequestDto) {
        const allowedFilters = {
            code: 'string',
            name: 'string',
            description: 'string',
            status: 'enum',
            beginEffective: 'date',
            endEffective: 'date',
        } as const

        const where = buildWhereClause(
            query,
            allowedFilters,
            ['code', 'name', 'description'],
        )

        const allowedSortColumns = ['code', 'name', 'status', 'createdAt']

        const orderBy: Prisma.HeaderSettingOrderByWithRelationInput = {}

        if (query.sort && allowedSortColumns.includes(query.sort)) {
            orderBy[query.sort] = query.sortOrder
        } else {
            orderBy.createdAt = 'desc'
        }

        const [total, rows] = await this.prisma.$transaction([
            this.prisma.headerSetting.count({ where }),
            this.prisma.headerSetting.findMany({
                where,
                skip: query.skip,
                take: query.take,
                orderBy,
            }),
        ])

        return new BootstrapTableResponseDto(total, rows)
    }

    findOneHeader(id: string) {
        return this.prisma.headerSetting.findUnique({
            where: { id },
            include: { details: true },
        })
    }

    updateHeader(id: string, data: UpdateHeaderDto) {
        return this.prisma.headerSetting.update({
            where: { id },
            data,
        })
    }

    removeHeader(id: string) {
        return this.prisma.headerSetting.delete({
            where: { id },
        })
    }

    // ================= DETAIL =================

    createDetail(data: CreateDetailDto) {
        console.log('Creating detail with data:', data)
        return this.prisma.detailSetting.create({
            data: {
                ...data,
                beginEffective: new Date(data.beginEffective),
                endEffective: data.endEffective
                    ? new Date(data.endEffective)
                    : null,
            },
        })
    }

    findAllDetails(query: BootstrapTableRequestDto) {
        const allowedFilters = {
            code: 'string',
            name: 'string',
            description: 'string',
            status: 'enum',
            beginEffective: 'date',
            endEffective: 'date',
        } as const

        const where = buildWhereClause(
            query,
            allowedFilters,
            ['code', 'name', 'description'],
        )

        const allowedSortColumns = ['code', 'name', 'status', 'createdAt']

        const orderBy: Prisma.DetailSettingOrderByWithRelationInput = {}

        if (query.sort && allowedSortColumns.includes(query.sort)) {
            orderBy[query.sort] = query.sortOrder
        } else {
            orderBy.createdAt = 'desc'
        }

        return this.prisma.detailSetting.findMany({
            where,
            include: { header: true },
            skip: query.skip,
            take: query.take,
            orderBy,
        })
    }

    findOneDetail(id: string) {
        return this.prisma.detailSetting.findUnique({
            where: { id },
            include: { header: true },
        })
    }

    updateDetail(id: string, data: UpdateDetailDto) {
        return this.prisma.detailSetting.update({
            where: { id },
            data: {
                ...data,
                beginEffective: data.beginEffective
                    ? new Date(data.beginEffective)
                    : undefined,
                endEffective: data.endEffective
                    ? new Date(data.endEffective)
                    : undefined,
            },
        })
    }

    removeDetail(id: string) {
        return this.prisma.detailSetting.delete({
            where: { id },
        })
    }
    // specific settings

    async findAllLovLm(query: BootstrapTableRequestDto) {
        const allowedFilters = {
            code: 'string',
            name: 'string',
            description: 'string',
            status: 'enum',
            beginEffective: 'date',
            endEffective: 'date',
        } as const

        const where = buildWhereClause(
            query,
            allowedFilters,
            ['code', 'name', 'description'],
        )

        const allowedSortColumns = ['code', 'name', 'status', 'createdAt']

        const orderBy: Prisma.DetailSettingOrderByWithRelationInput = {}

        if (query.sort && allowedSortColumns.includes(query.sort)) {
            orderBy[query.sort] = query.sortOrder
        } else {
            orderBy.createdAt = 'desc'
        }

        const [total, rows] = await this.prisma.$transaction([
            this.prisma.detailSetting.count({
                where: {
                    ...where,
                    header: { code: 'LOV_LM_TYPES' },
                },
            }),
            this.prisma.detailSetting.findMany({
                where: {
                    ...where,
                    header: { code: 'LOV_LM_TYPES' },
                },
                include: { header: true },
                skip: query.skip,
                take: query.take,
                orderBy,
            }),
        ])

        return new BootstrapTableResponseDto(total, rows)
    }
    async findAllLovJewelry(query: BootstrapTableRequestDto) {
        const allowedFilters = {
            code: 'string',
            name: 'string',
            description: 'string',
            status: 'enum',
            beginEffective: 'date',
            endEffective: 'date',
        } as const

        const where = buildWhereClause(
            query,
            allowedFilters,
            ['code', 'name', 'description'],
        )

        const allowedSortColumns = ['code', 'name', 'status', 'createdAt']

        const orderBy: Prisma.DetailSettingOrderByWithRelationInput = {}

        if (query.sort && allowedSortColumns.includes(query.sort)) {
            orderBy[query.sort] = query.sortOrder
        } else {
            orderBy.createdAt = 'desc'
        }

        const [total, rows] = await this.prisma.$transaction([
            this.prisma.detailSetting.count({
                where: {
                    ...where,
                    header: { code: 'LOV_JEWELRY_TYPES' },
                },
            }),
            this.prisma.detailSetting.findMany({
                where: {
                    ...where,
                    header: { code: 'LOV_JEWELRY_TYPES' },
                },
                include: { header: true },
                skip: query.skip,
                take: query.take,
                orderBy,
            }),
        ])

        return new BootstrapTableResponseDto(total, rows)
    }

    async findAllLovReferralSource(query: BootstrapTableRequestDto) {
        const allowedFilters = {
            code: 'string',
            name: 'string',
            description: 'string',
            status: 'enum',
            beginEffective: 'date',
            endEffective: 'date',
        } as const

        const where = buildWhereClause(
            query,
            allowedFilters,
            ['code', 'name', 'description'],
        )

        const allowedSortColumns = ['code', 'name', 'status', 'createdAt']

        const orderBy: Prisma.DetailSettingOrderByWithRelationInput = {}

        if (query.sort && allowedSortColumns.includes(query.sort)) {
            orderBy[query.sort] = query.sortOrder
        } else {
            orderBy.createdAt = 'desc'
        }

        const [total, rows] = await this.prisma.$transaction([
            this.prisma.detailSetting.count({
                where: {
                    ...where,
                    header: { code: 'REFERRAL_SOURCE' },
                },
            }),
            this.prisma.detailSetting.findMany({
                where: {
                    ...where,
                    header: { code: 'REFERRAL_SOURCE' },
                },
                include: { header: true },
                skip: query.skip,
                take: query.take,
                orderBy,
            }),
        ])

        return new BootstrapTableResponseDto(total, rows)
    }

    async findAllLovCancellationReason(query: BootstrapTableRequestDto) {
        const allowedFilters = {
            code: 'string',
            name: 'string',
            description: 'string',
            status: 'enum',
            beginEffective: 'date',
            endEffective: 'date',
        } as const

        const where = buildWhereClause(
            query,
            allowedFilters,
            ['code', 'name', 'description'],
        )

        const allowedSortColumns = ['code', 'name', 'status', 'createdAt']

        const orderBy: Prisma.DetailSettingOrderByWithRelationInput = {}

        if (query.sort && allowedSortColumns.includes(query.sort)) {
            orderBy[query.sort] = query.sortOrder
        } else {
            orderBy.createdAt = 'desc'
        }

        const [total, rows] = await this.prisma.$transaction([
            this.prisma.detailSetting.count({
                where: {
                    ...where,
                    header: { code: 'CANCELLATION_REASON' },
                },
            }),
            this.prisma.detailSetting.findMany({
                where: {
                    ...where,
                    header: { code: 'CANCELLATION_REASON' },
                },
                include: { header: true },
                skip: query.skip,
                take: query.take,
                orderBy,
            }),
        ])

        return new BootstrapTableResponseDto(total, rows)
    }
}