import { z } from "zod";
import { and, eq, sql } from "drizzle-orm";
import { db } from "@/lib/db";
import { registerItemToggleHook } from "../_core/registry";
import type { ModuleManifest, WidgetContext } from "../_core/module";
import {
  loadContainerForShare,
  loadPlantForShare,
  type ContainerShareData,
  type PlantShareData,
} from "./server/share-queries";
import {
  listContainers,
  searchContainers,
  searchPlants,
  getCareDueWidgetRows,
  getGardenOverviewStats,
} from "./server/queries";
import { CareDueWidget, GardenOverviewWidget } from "./components/plant-widget";

const careDueConfigSchema = z.object({
  containerIds: z.union([z.literal("all"), z.array(z.string().uuid())]),
  daysAhead: z.number().int().min(0).max(30).default(0),
});

async function CareDueWidgetServer({ config, ctx }: { config: unknown; ctx: WidgetContext }) {
  const parsed = careDueConfigSchema.parse(config);
  const rows = await getCareDueWidgetRows(ctx.householdId, parsed.containerIds, parsed.daysAhead);
  return <CareDueWidget rows={rows} />;
}

async function GardenOverviewWidgetServer({ ctx }: { config: unknown; ctx: WidgetContext }) {
  const stats = await getGardenOverviewStats(ctx.householdId);
  return <GardenOverviewWidget stats={stats} />;
}

const gardenManifest: ModuleManifest = {
  id: "garden",
  name: "Garden",
  nav: { href: "/garden", label: "Garden", icon: "sprout" },
  entities: [
    {
      type: "garden.plant",
      label: { singular: "Plant", plural: "Plants" },
      share: { canShare: true, defaultCapabilities: ["read"] },
      search: { search: searchPlants },
      resolveUrl: (id) => `/garden/plants/${id}`,
      loadForShare: (id) => loadPlantForShare(id),
      renderSharedView: ({ data }) => {
        const d = data as PlantShareData;
        return (
          <div className="flex flex-col gap-3">
            {d.primaryImageUrl && (
              <img
                src={d.primaryImageUrl}
                alt=""
                className="w-full max-h-48 object-cover rounded-lg"
              />
            )}
            <h2 className="text-xl font-bold">{d.name}</h2>
            {d.scientificName && (
              <p className="text-sm italic text-[var(--ink-mute)]">{d.scientificName}</p>
            )}
            <p className="text-sm capitalize">
              {d.healthStatus} · {d.category}
            </p>
            {d.wateringNotes && (
              <div>
                <p className="text-xs font-semibold uppercase text-[var(--ink-mute)] mb-1">
                  Watering
                </p>
                <p className="text-sm">{d.wateringNotes}</p>
              </div>
            )}
            {d.fertilizingNotes && (
              <div>
                <p className="text-xs font-semibold uppercase text-[var(--ink-mute)] mb-1">
                  Fertilizing
                </p>
                <p className="text-sm">{d.fertilizingNotes}</p>
              </div>
            )}
            {d.notes && <p className="text-sm">{d.notes}</p>}
            {d.images.length > 1 && (
              <div className="grid grid-cols-3 gap-2 mt-1">
                {d.images.slice(1).map((url) => (
                  <img
                    key={url}
                    src={url}
                    alt=""
                    className="w-full aspect-square object-cover rounded"
                  />
                ))}
              </div>
            )}
          </div>
        );
      },
      renderActivity: (entry) => {
        const name = entry.payload?.name as string | undefined;
        if (entry.action === "create") return `Added plant${name ? ` "${name}"` : ""}`;
        if (entry.action === "delete") return `Removed plant${name ? ` "${name}"` : ""}`;
        return `Updated${name ? ` "${name}"` : " plant"}`;
      },
    },
    {
      type: "garden.container",
      label: { singular: "Container", plural: "Containers" },
      share: { canShare: true, defaultCapabilities: ["read"] },
      search: { search: searchContainers },
      resolveUrl: (id) => `/garden/containers/${id}`,
      loadForShare: (id) => loadContainerForShare(id),
      renderSharedView: ({ data }) => {
        const d = data as ContainerShareData;
        return (
          <div className="flex flex-col gap-3">
            <h2 className="text-xl font-bold">{d.name}</h2>
            <p className="text-sm capitalize text-[var(--ink-mute)]">{d.type}</p>
            {d.locationNotes && <p className="text-sm">{d.locationNotes}</p>}
            {d.plants.length > 0 && (
              <div>
                <p className="text-sm font-medium mb-1">Plants</p>
                <ul className="text-sm space-y-1">
                  {d.plants.map((p) => (
                    <li key={p.id}>
                      {p.name}
                      {p.scientificName && (
                        <span className="text-[var(--ink-mute)] italic ml-1">
                          ({p.scientificName})
                        </span>
                      )}
                    </li>
                  ))}
                </ul>
              </div>
            )}
          </div>
        );
      },
      renderActivity: (entry) => {
        const name = entry.payload?.name as string | undefined;
        if (entry.action === "create") return `Created container${name ? ` "${name}"` : ""}`;
        if (entry.action === "delete") return "Deleted container";
        return `Updated container${name ? ` "${name}"` : ""}`;
      },
    },
  ],
  dashboardWidgets: [
    {
      id: "garden.care-due",
      title: "Plants needing care",
      description: "Shows plants with overdue or upcoming care schedules.",
      category: "Garden",
      defaultSize: { w: 4, h: 4 },
      minSize: { w: 3, h: 2 },
      defaultPriority: 40,
      configSchema: careDueConfigSchema,
      defaultConfig: { containerIds: "all", daysAhead: 0 },
      resolveConfigOptions: async () => ({
        containers: (await listContainers()).map((c) => ({ id: c.id, name: c.name })),
      }),
      render: (props) => <CareDueWidgetServer {...props} />,
    },
    {
      id: "garden.overview",
      title: "Garden overview",
      description: "Plant and container counts with next care summary.",
      category: "Garden",
      defaultSize: { w: 3, h: 2 },
      minSize: { w: 2, h: 2 },
      defaultPriority: 41,
      configSchema: z.object({}),
      defaultConfig: {},
      render: (props) => <GardenOverviewWidgetServer {...props} />,
    },
  ],
  quickAdds: [
    {
      id: "garden.add-plant",
      label: "Add plant",
      icon: "leaf",
      url: "/garden/plants/new",
    },
    {
      id: "garden.add-container",
      label: "Add container",
      icon: "box",
      url: "/garden/containers/new",
    },
    {
      id: "garden.log-care",
      label: "Log plant care",
      icon: "droplets",
      url: "/garden?logCare=1",
    },
  ],
};

import { gardenCareLogs, gardenPlants } from "./schema";

registerItemToggleHook("garden.care-task", async ({ metadata, done, userId }) => {
  if (!done) return;
  const plantId = metadata.gardenPlantId;
  const careType = metadata.gardenCareType;
  if (typeof plantId !== "string" || typeof careType !== "string") return;

  const [plant] = await db
    .select({ householdId: gardenPlants.householdId })
    .from(gardenPlants)
    .where(eq(gardenPlants.id, plantId))
    .limit(1);

  if (!plant) return;

  // Avoid duplicate log if care was already logged within the last 10 minutes
  const recentLog = await db
    .select({ id: gardenCareLogs.id })
    .from(gardenCareLogs)
    .where(
      and(
        eq(gardenCareLogs.plantId, plantId),
        eq(gardenCareLogs.careType, careType),
        sql`${gardenCareLogs.performedAt} > now() - interval '10 minutes'`,
      ),
    )
    .limit(1);

  if (recentLog[0]) return;

  await db.insert(gardenCareLogs).values({
    plantId,
    householdId: plant.householdId,
    careType,
    performedBy: userId,
    notes: "Logged via task list",
    performedAt: new Date(),
  });
});

export default gardenManifest;
