import { Injectable } from '@nestjs/common';
import { PrismaService } from '../infra/prisma.service';
import { UpsertSettingCommand } from './dto';
import { PUBLIC_SETTING_KEYS } from './system-settings.seed';

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

  async getValue(key: string, fallback: string): Promise<string> {
    const setting = await this.prisma.systemSetting.findUnique({ where: { key } });
    return setting?.value ?? fallback;
  }

  async getNumber(key: string, fallback: number): Promise<number> {
    const raw = await this.getValue(key, String(fallback));
    const parsed = Number(raw);
    return Number.isFinite(parsed) ? parsed : fallback;
  }

  async getBoolean(key: string, fallback: boolean): Promise<boolean> {
    const raw = (await this.getValue(key, fallback ? 'true' : 'false')).trim().toLowerCase();
    if (raw === 'true' || raw === '1' || raw === 'yes') return true;
    if (raw === 'false' || raw === '0' || raw === 'no') return false;
    return fallback;
  }

  async listPublic() {
    return this.prisma.systemSetting.findMany({
      where: { key: { in: [...PUBLIC_SETTING_KEYS] }, isSecret: false },
      orderBy: { key: 'asc' }
    });
  }

  async list() {
    return this.prisma.systemSetting.findMany({ orderBy: { key: 'asc' } });
  }

  async get(key: string) {
    return this.prisma.systemSetting.findUniqueOrThrow({ where: { key } });
  }

  async upsert(command: UpsertSettingCommand) {
    const trimmedValue = command.value?.trim() ?? '';
    if (command.isSecret && trimmedValue === '') {
      const existing = await this.prisma.systemSetting.findUnique({ where: { key: command.key } });
      if (existing) {
        return this.prisma.systemSetting.update({
          where: { key: command.key },
          data: {
            description: command.description,
            isSecret: command.isSecret ?? existing.isSecret
          }
        });
      }
    }

    return this.prisma.systemSetting.upsert({
      where: { key: command.key },
      create: {
        key: command.key,
        value: command.value,
        description: command.description,
        isSecret: command.isSecret ?? false
      },
      update: {
        value: command.value,
        description: command.description,
        isSecret: command.isSecret ?? false
      }
    });
  }

  async delete(key: string) {
    await this.prisma.systemSetting.delete({ where: { key } });
    return { count: 1 };
  }

  async listSocialProviders() {
    return this.prisma.socialProvider.findMany({ orderBy: { providerName: 'asc' } });
  }

  async upsertSocialProvider(command: { providerName: string; clientId: string; clientSecret?: string; isEnabled: boolean }) {
    return this.prisma.socialProvider.upsert({
      where: { providerName: command.providerName },
      create: command,
      update: {
        clientId: command.clientId,
        clientSecret: command.clientSecret,
        isEnabled: command.isEnabled
      }
    });
  }

  async deleteSocialProvider(providerName: string) {
    await this.prisma.socialProvider.delete({ where: { providerName } });
    return { count: 1 };
  }
}
