import type { App, TFile } from "obsidian";
import { randomUUID } from "../utils/id";
import type { HaloClient } from "./client";
import type { Post, Snapshot, Content } from "./types";
import { HaloError } from "./error";
import { ApiPaths } from "../utils/api-paths";

export class PostService {
  constructor(
    private app: App,
    private client: HaloClient,
  ) {}

  async getPost(name: string): Promise<{ post: Post; content: Content } | undefined> {
    try {
      const post = await this.client.get<Post>(ApiPaths.posts.get(name));

      const snapshot = await this.client.get<Snapshot>(ApiPaths.posts.getDraft(name));

      const { "content.halo.run/patched-content": patchedContent, "content.halo.run/patched-raw": patchedRaw } =
        snapshot.metadata.annotations || {};

      const { rawType } = snapshot.spec || {};

      const content: Content = {
        content: patchedContent,
        raw: patchedRaw,
        rawType,
      };

      return { post, content };
    } catch (error) {
      if (error instanceof HaloError && error.isNotFound()) {
        return undefined;
      }
      throw error;
    }
  }

  async createPost(params: Post): Promise<Post> {
    return await this.client.post<Post>(ApiPaths.posts.create(), params);
  }

  async updatePost(name: string, params: Post): Promise<void> {
    await this.client.put(ApiPaths.posts.update(name), params);
  }

  async deletePost(name: string): Promise<void> {
    await this.client.delete(ApiPaths.posts.delete(name));
  }

  async changePublishStatus(name: string, publish: boolean): Promise<void> {
    await this.client.putVoid(publish ? ApiPaths.posts.publish(name) : ApiPaths.posts.unpublish(name));
  }

  async createPostFromFile(
    file: TFile,
    content: Content,
    frontmatter: Record<string, unknown>,
  ): Promise<Post> {
    const params: Post = {
      apiVersion: "content.halo.run/v1alpha1",
      kind: "Post",
      metadata: {
        annotations: {
          "content.halo.run/content-json": JSON.stringify(content),
        },
        name: randomUUID(),
      },
      spec: {
        allowComment: true,
        baseSnapshot: "",
        categories: [],
        cover: (frontmatter.cover as string) || "",
        deleted: false,
        excerpt: {
          autoGenerate: frontmatter.excerpt ? false : true,
          raw: (frontmatter.excerpt as string) || "",
        },
        headSnapshot: "",
        htmlMetas: [],
        owner: "",
        pinned: false,
        priority: 0,
        publish: false,
        publishTime: "",
        releaseSnapshot: "",
        slug: (frontmatter.slug as string) || "",
        tags: [],
        template: "",
        title: (frontmatter.title as string) || file.basename,
        visible: "PUBLIC",
      },
    };

    return await this.createPost(params);
  }
}
