import { Body, Controller, Post, Route, Security, SuccessResponse, Tags } from "tsoa";
import HttpStatusCode from "../interfaces/http-status";
import esClient from "../elasticsearch";
import { Search } from "../interfaces/search";
import { StorageFile } from "../interfaces/storage-fs";

const DEFAULT_INDEX = process.env.ELASTICSEARCH_INDEX;

if (!DEFAULT_INDEX) throw Error("Default ElasticSearch index must be specified.");

@Route("/search")
export class SearchController extends Controller {
  @Post("/")
  @Tags("ค้นหา")
  @Security("bearerAuth")
  @SuccessResponse(HttpStatusCode.OK, "สำเร็จ")
  public async searchFile(@Body() search: Search): Promise<StorageFile[]> {
    const type = ["match", "match_phrase"] as const;

    const result = await esClient.search<StorageFile & { attachment: Record<string, string> }>({
      index: DEFAULT_INDEX,
      query: {
        bool: {
          must: search.AND?.map((v) => ({
            [type[search.exact || v.exact ? 1 : 0]]: { [v.field]: v.value },
          })),
          should: search.OR?.map((v) => ({
            [type[search.exact || v.exact ? 1 : 0]]: { [v.field]: v.value },
          })),
        },
      },
      size: 10000,
    });

    return result.hits.hits.length > 0
      ? result.hits.hits
          .map((v) => {
            if (!v._source) return;

            const { attachment, ...rest } = v._source;

            return rest;
          })
          .flatMap((v) => (!!v ? [v] : []))
      : [];
  }
}
