<template>
  <q-page class="api-tester-page">
    <div class="page-shell">
      <header class="page-header">
        <p class="eyebrow">Developer tools</p>
        <h1>API Endpoints Tester</h1>
        <p class="subtitle">
          Lista endpoint generata da <strong>src/api/api.ts</strong> con form payload, esecuzione
          rapida e risposta formattata.
        </p>
      </header>

      <section class="cards-grid">
        <q-card
          v-for="endpoint in endpoints"
          :key="endpoint.key"
          flat
          bordered
          class="endpoint-card"
        >
          <q-card-section class="card-head">
            <div class="head-main">
              <q-badge
                :color="endpoint.method === 'GET' ? 'positive' : 'primary'"
                text-color="white"
                :label="endpoint.method"
              />
              <code>{{ endpoint.path }}</code>
            </div>
            <div class="text-h6">{{ endpoint.name }}</div>
            <div class="text-caption text-grey-7">{{ endpoint.signature }}</div>
          </q-card-section>

          <q-separator />

          <q-card-section class="card-body">
            <div v-if="endpoint.fields.length === 0" class="no-fields">
              Nessun dato richiesto da questo endpoint.
            </div>

            <div v-else class="field-grid">
              <div
                v-for="field in endpoint.fields"
                :key="`${endpoint.key}-${field.key}`"
                class="field-item"
              >
                <q-input
                  v-if="field.type !== 'number'"
                  v-model="getForm(endpoint.key)[field.key]"
                  :label="field.label"
                  :type="field.type"
                  :hint="field.hint"
                  :placeholder="field.placeholder"
                  dense
                  outlined
                  autogrow
                />

                <q-input
                  v-else
                  v-model.number="getForm(endpoint.key)[field.key]"
                  :label="field.label"
                  type="number"
                  :hint="field.hint"
                  :placeholder="field.placeholder"
                  dense
                  outlined
                />
              </div>
            </div>
          </q-card-section>

          <q-card-actions align="between" class="card-actions">
            <q-btn
              flat
              color="secondary"
              icon="restart_alt"
              label="Reset"
              @click="resetForm(endpoint.key)"
            />
            <q-btn
              color="accent"
              icon="play_arrow"
              label="Test"
              :loading="loading[endpoint.key]"
              @click="runEndpoint(endpoint)"
            />
          </q-card-actions>
        </q-card>
      </section>
    </div>

    <q-dialog v-model="resultDialogOpen" maximized>
      <q-card class="result-card">
        <q-card-section class="result-header">
          <div class="text-overline">Risultato endpoint</div>
          <div class="text-h6">{{ resultMeta.name }}</div>
          <div class="text-caption">{{ resultMeta.method }} {{ resultMeta.path }}</div>
        </q-card-section>

        <q-separator />

        <q-card-section class="result-body">
          <div class="result-block">
            <h3>Payload inviato</h3>
            <pre>{{ formatJson(resultPayload) }}</pre>
          </div>

          <div class="result-block">
            <h3>Risposta</h3>
            <pre>{{ formatJson(resultResponse) }}</pre>
          </div>
        </q-card-section>

        <q-card-actions align="right">
          <q-btn flat color="primary" label="Chiudi" v-close-popup />
        </q-card-actions>
      </q-card>
    </q-dialog>
  </q-page>
</template>

<script setup lang="ts">
import { reactive, ref } from 'vue';
import {
  forgotPassword,
  health,
  listUsers,
  login,
  me,
  metrics,
  refresh,
  register,
  resetPassword,
} from 'src/api/api';
import type { UserCreateInput } from 'src/api/api';

type Method = 'GET' | 'POST';
type FieldType = 'text' | 'password' | 'number' | 'textarea';

type FormState = Record<string, string | number>;

interface EndpointField {
  key: string;
  label: string;
  type: FieldType;
  placeholder?: string;
  hint?: string;
}

interface EndpointConfig {
  key: string;
  name: string;
  method: Method;
  path: string;
  signature: string;
  fields: EndpointField[];
  defaults: FormState;
  call: (payload: unknown) => Promise<unknown>;
  buildPayload: (form: FormState) => unknown;
}

const endpoints: EndpointConfig[] = [
  {
    key: 'forgotPassword',
    name: 'forgotPassword',
    method: 'POST',
    path: '/auth/password/forgot',
    signature:
      'Typescript: TSEndpoint= path=/auth/password/forgot; name=forgotPassword; method=POST',
    fields: [
      {
        key: 'email',
        label: 'Email',
        type: 'text',
        placeholder: 'user@example.com',
      },
    ],
    defaults: { email: '' },
    call: (payload) => forgotPassword(payload as { email: string }),
    buildPayload: (form) => ({ email: String(form.email ?? '') }),
  },
  {
    key: 'metrics',
    name: 'metrics',
    method: 'GET',
    path: '/metrics',
    signature: 'Typescript: TSEndpoint= path=/metrics; name=metrics; method=GET',
    fields: [],
    defaults: {},
    call: () => metrics(),
    buildPayload: () => null,
  },
  {
    key: 'login',
    name: 'login',
    method: 'POST',
    path: '/auth/login',
    signature: 'Typescript: TSEndpoint= path=/auth/login; name=login; method=POST',
    fields: [
      {
        key: 'username',
        label: 'Username',
        type: 'text',
        placeholder: 'utente',
      },
      {
        key: 'password',
        label: 'Password',
        type: 'password',
        placeholder: '********',
      },
    ],
    defaults: { username: '', password: '' },
    call: (payload) => login(payload as { username: string; password: string }),
    buildPayload: (form) => ({
      username: String(form.username ?? ''),
      password: String(form.password ?? ''),
    }),
  },
  {
    key: 'refresh',
    name: 'refresh',
    method: 'POST',
    path: '/auth/refresh',
    signature: 'Typescript: TSEndpoint= path=/auth/refresh; name=refresh; method=POST',
    fields: [
      {
        key: 'refresh_token',
        label: 'Refresh token',
        type: 'textarea',
        hint: 'Incolla il token completo',
      },
    ],
    defaults: { refresh_token: '' },
    call: (payload) => refresh(payload as { refresh_token: string }),
    buildPayload: (form) => ({
      refresh_token: String(form.refresh_token ?? ''),
    }),
  },
  {
    key: 'listUsers',
    name: 'listUsers',
    method: 'POST',
    path: '/admin/users',
    signature: 'Typescript: TSEndpoint= path=/admin/users; name=listUsers; method=POST',
    fields: [
      {
        key: 'page',
        label: 'Page',
        type: 'number',
        placeholder: '1',
      },
      {
        key: 'pageSize',
        label: 'Page size',
        type: 'number',
        placeholder: '10',
      },
    ],
    defaults: { page: 1, pageSize: 10 },
    call: (payload) => listUsers(payload as { page: number; pageSize: number }),
    buildPayload: (form) => ({
      page: Number(form.page ?? 1),
      pageSize: Number(form.pageSize ?? 10),
    }),
  },
  {
    key: 'me',
    name: 'me',
    method: 'GET',
    path: '/auth/me',
    signature: 'Typescript: TSEndpoint= path=/auth/me; name=me; method=GET',
    fields: [],
    defaults: {},
    call: () => me(),
    buildPayload: () => null,
  },
  {
    key: 'resetPassword',
    name: 'resetPassword',
    method: 'POST',
    path: '/auth/password/reset',
    signature: 'Typescript: TSEndpoint= path=/auth/password/reset; name=resetPassword; method=POST',
    fields: [
      {
        key: 'token',
        label: 'Token',
        type: 'textarea',
      },
      {
        key: 'password',
        label: 'Nuova password',
        type: 'password',
      },
    ],
    defaults: { token: '', password: '' },
    call: (payload) => resetPassword(payload as { token: string; password: string }),
    buildPayload: (form) => ({
      token: String(form.token ?? ''),
      password: String(form.password ?? ''),
    }),
  },
  {
    key: 'health',
    name: 'health',
    method: 'GET',
    path: '/health',
    signature: 'Typescript: TSEndpoint= path=/health; name=health; method=GET',
    fields: [],
    defaults: {},
    call: () => health(),
    buildPayload: () => null,
  },
  {
    key: 'register',
    name: 'register',
    method: 'POST',
    path: '/auth/register',
    signature: 'Typescript: TSEndpoint= path=/auth/register; name=register; method=POST',
    fields: [
      {
        key: 'name',
        label: 'Name',
        type: 'text',
      },
      {
        key: 'email',
        label: 'Email',
        type: 'text',
      },
      {
        key: 'password',
        label: 'Password',
        type: 'password',
      },
      {
        key: 'roles',
        label: 'Roles (comma separated)',
        type: 'text',
        placeholder: 'admin,editor',
      },
      {
        key: 'status',
        label: 'Status',
        type: 'text',
        placeholder: 'pending | active | disabled',
      },
      {
        key: 'types',
        label: 'Types (comma separated)',
        type: 'text',
        placeholder: 'internal,staff',
      },
      {
        key: 'avatar',
        label: 'Avatar URL',
        type: 'text',
      },
      {
        key: 'details',
        label: 'Details JSON',
        type: 'textarea',
        hint: 'Lascia vuoto per null',
        placeholder:
          '{"title":"Sig.","firstName":"Mario","lastName":"Rossi","address":"Via Roma 1","city":"Roma","zipCode":"00100","country":"IT","phone":"+39..."}',
      },
      {
        key: 'preferences',
        label: 'Preferences JSON',
        type: 'textarea',
        hint: 'Lascia vuoto per null',
        placeholder:
          '{"useIdle":true,"idleTimeout":15,"useIdlePassword":false,"idlePin":"","useDirectLogin":true,"useQuadcodeLogin":false,"sendNoticesMail":true,"language":"it"}',
      },
    ],
    defaults: {
      name: '',
      email: '',
      password: '',
      roles: 'user',
      status: 'pending',
      types: 'default',
      avatar: '',
      details: '',
      preferences: '',
    },
    call: (payload) => register(payload as UserCreateInput),
    buildPayload: (form) => ({
      name: String(form.name ?? ''),
      email: String(form.email ?? ''),
      password: String(form.password ?? ''),
      roles: parseCsv(String(form.roles ?? '')),
      status: String(form.status ?? 'pending'),
      types: parseCsv(String(form.types ?? '')),
      avatar: emptyToNull(String(form.avatar ?? '')),
      details: parseJsonOrNull(String(form.details ?? '')),
      preferences: parseJsonOrNull(String(form.preferences ?? '')),
    }),
  },
];

const forms = reactive<Record<string, FormState>>({});
const loading = reactive<Record<string, boolean>>({});

for (const endpoint of endpoints) {
  forms[endpoint.key] = { ...endpoint.defaults };
  loading[endpoint.key] = false;
}

const resultDialogOpen = ref(false);
const resultMeta = ref({ name: '', method: '', path: '' });
const resultPayload = ref<unknown>(null);
const resultResponse = ref<unknown>(null);

function parseCsv(value: string): string[] {
  return value
    .split(',')
    .map((item) => item.trim())
    .filter((item) => item.length > 0);
}

function emptyToNull(value: string): string | null {
  return value.trim() === '' ? null : value;
}

function parseJsonOrNull(value: string): unknown {
  if (value.trim() === '') {
    return null;
  }

  try {
    return JSON.parse(value);
  } catch {
    return { _raw: value };
  }
}

function resetForm(endpointKey: string): void {
  const endpoint = endpoints.find((item) => item.key === endpointKey);
  if (!endpoint) {
    return;
  }

  forms[endpointKey] = { ...endpoint.defaults };
}

function getForm(endpointKey: string): FormState {
  if (!forms[endpointKey]) {
    forms[endpointKey] = {};
  }

  return forms[endpointKey];
}

async function runEndpoint(endpoint: EndpointConfig): Promise<void> {
  loading[endpoint.key] = true;

  const payload = endpoint.buildPayload(getForm(endpoint.key));
  resultMeta.value = {
    name: endpoint.name,
    method: endpoint.method,
    path: endpoint.path,
  };
  resultPayload.value = payload;

  try {
    const response = await endpoint.call(payload);
    resultResponse.value = response;
  } catch (error) {
    resultResponse.value = {
      error: error instanceof Error ? error.message : String(error),
    };
  } finally {
    loading[endpoint.key] = false;
    resultDialogOpen.value = true;
  }
}

function formatJson(value: unknown): string {
  if (typeof value === 'string') {
    return value;
  }

  try {
    return JSON.stringify(value, null, 2);
  } catch {
    return String(value);
  }
}
</script>

<style scoped>
.api-tester-page {
  background:
    radial-gradient(circle at 15% 20%, #fcecc9 0%, transparent 32%),
    radial-gradient(circle at 85% 10%, #d8f4f8 0%, transparent 35%),
    linear-gradient(145deg, #f7f3ec 0%, #eef8f9 100%);
  min-height: 100vh;
  padding: 28px 16px 36px;
}

.page-shell {
  max-width: 1240px;
  margin: 0 auto;
}

.page-header {
  margin-bottom: 20px;
}

.eyebrow {
  margin: 0;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: #395f76;
  font-weight: 700;
  font-size: 11px;
}

.page-header h1 {
  margin: 6px 0;
  font-family: 'Space Grotesk', sans-serif;
  font-size: clamp(1.6rem, 2.8vw, 2.3rem);
}

.subtitle {
  margin: 0;
  color: #50626f;
  max-width: 760px;
}

.cards-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
  gap: 16px;
}

.endpoint-card {
  border-radius: 14px;
  backdrop-filter: blur(4px);
  background: rgba(255, 255, 255, 0.75);
}

.card-head {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.head-main {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.head-main code {
  background: #f1f4f7;
  border: 1px solid #dce5eb;
  border-radius: 8px;
  padding: 2px 8px;
}

.card-body {
  min-height: 160px;
}

.no-fields {
  padding: 8px;
  color: #60717f;
}

.field-grid {
  display: grid;
  gap: 10px;
}

.card-actions {
  padding: 12px 16px 16px;
}

.result-card {
  background: #0f1a24;
  color: #e7edf3;
}

.result-header {
  background: linear-gradient(90deg, #152434 0%, #244661 100%);
}

.result-body {
  display: grid;
  grid-template-columns: 1fr;
  gap: 16px;
  max-height: calc(100vh - 210px);
  overflow-y: auto;
}

.result-block {
  background: #162432;
  border: 1px solid #2c465f;
  border-radius: 12px;
  padding: 12px;
}

.result-block h3 {
  margin: 0 0 8px;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: #9bc2de;
}

.result-block pre {
  margin: 0;
  white-space: pre-wrap;
  word-break: break-word;
  font-size: 12px;
}

@media (max-width: 640px) {
  .api-tester-page {
    padding-top: 18px;
  }

  .cards-grid {
    grid-template-columns: 1fr;
  }
}
</style>
