

import type { CachePort } from "../cache/cache-port.js";
import { config } from "../../config.js";
import type {
  CreateMasterInput,
  MasterFilter,
  MasterPage,
  MasterRecord,
  MasterRepository,
  UpdateMasterInput,
} from "./domain.js";

export class MasterDataService {
  constructor(
    private readonly repo: MasterRepository,
    private readonly cache: CachePort
  ) {}

  async list(domain: string, filter: MasterFilter): Promise<MasterPage> {
    const key = `master:list:${domain}:${filter.page}:${filter.limit}:${filter.q ?? ""}:${filter.parentId ?? ""}:${filter.isActive ?? ""}`;
    const cached = await this.cache.get<MasterPage>(key);
    if (cached) return cached;

    const page = await this.repo.list(domain, filter);
    await this.cache.set(key, page, config.masterTtlSeconds);
    return page;
  }

  async getById(domain: string, id: string): Promise<MasterRecord | null> {
    const key = `master:item:${domain}:${id}`;
    const cached = await this.cache.get<MasterRecord>(key);
    if (cached) return cached;

    const record = await this.repo.getById(domain, id);
    if (record) {
      await this.cache.set(key, record, config.masterTtlSeconds);
    }
    return record;
  }

  async create(domain: string, data: CreateMasterInput): Promise<MasterRecord> {
    const record = await this.repo.create(domain, data);
    await this.cache.delByPrefix(`master:list:${domain}:`);
    return record;
  }

  async update(domain: string, id: string, data: UpdateMasterInput): Promise<MasterRecord | null> {
    const record = await this.repo.update(domain, id, data);
    await Promise.all([
      this.cache.delByPrefix(`master:list:${domain}:`),
      this.cache.delByPrefix(`master:item:${domain}:${id}`),
    ]);
    return record;
  }

  async softDelete(domain: string, id: string): Promise<boolean> {
    const deleted = await this.repo.softDelete(domain, id);
    await Promise.all([
      this.cache.delByPrefix(`master:list:${domain}:`),
      this.cache.delByPrefix(`master:item:${domain}:${id}`),
    ]);
    return deleted;
  }
}
