// Card.tsx
import React, { useEffect, useMemo, useState } from 'react';
import { Trans } from '@lingui/macro';
import CardMui from '@mui/material/Card';
import styled from 'styled-components';
import { PointItem } from '../requests';
import '../../share/dialogPopup.tsx';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';
import Tooltip from '@mui/material/Tooltip';
import IconButton from '@mui/material/IconButton';
import Autocomplete from '@mui/material/Autocomplete';
import TextField from '@mui/material/TextField';
import Chip from '@mui/material/Chip';
import AddIcon from '@mui/icons-material/Add';
import CloseRoundedIcon from '@mui/icons-material/CloseRounded';

export const FlatButton = styled.button`
  outline: none;
  border: none;
  border-radius: 2px;
  background: 0 0;
  &:hover {
    background-color: rgba(158, 158, 158, 0.2);
  }
`;

const StyledCard = styled(CardMui)`
  display: flex;
  overflow: hidden;
  margin-bottom: 1em;
  font-size: 1rem;
`;

const Color = styled.div`
  align-self: stretch;
  background-color: ${(props) => (props as any).color ?? ''};
  min-width: 1.5em;
  border-right: 1px solid rgba(0, 0, 0, 0.15);
`;

const Info = styled.div`
  display: block;
  padding: 1em;
  margin-right: auto;
  width: 100%;
`;

const StyledDate = styled.div`
  font-family: 'Roboto', sans-serif !important;
  font-size: 13px;
  font-weight: 400;
`;

const StyledID = styled.div`
  font-family: 'Roboto', sans-serif !important;
  cursor: pointer;
  font-weight: 400;
  font-size: 15px;
  color: #0099ff;

  width: 4.7rem;
  height: 18px;

  border-radius: 5px;
  padding-right: 5px;
  padding-left: 5px;

  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;

  background: var(--Google-Background, #ecf4fe);
`;

const StyledComment = styled.div`
  font-family: 'Roboto', sans-serif !important;
  font-weight: 400;
  white-space: pre-line;
  margin-top: 0.5em;
  line-height: 22px;
  font-size: 15px;
`;

const GroupName = styled.div`
  font-family: 'Roboto', sans-serif !important;
  font-weight: 400;
  font-size: 12px;
  line-height: 18px;
  letter-spacing: 0%;
  color: rgba(0, 153, 255, 1);
`;

const FooterRow = styled.div`
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin: 10px;
  gap: 12px;
  flex-wrap: wrap;
`;

const IconContainer = styled.div`
  display: flex;
  align-items: center;
  gap: 8px;
`;

const FillAvailable = styled.div`
  display: flex;
  flex-direction: column;
  width: -moz-available;
  width: -webkit-fill-available;
  width: fill-available;
  flex-grow: 1;
`;

const TagRow = styled.div`
  display: flex;
  align-items: center;
  gap: 6px;
`;

/* ---------------- Helpers: Tag-Normalisierung ---------------- */
const uniqueOrder = (arr: string[]): string[] => {
  const seen = new Set<string>();
  const out: string[] = [];
  for (const s of arr) {
    const clean = String(s ?? '').trim();
    if (!clean) continue;
    const key = clean.toLowerCase();
    if (!seen.has(key)) {
      seen.add(key);
      out.push(clean);
    }
  }
  return out;
};

const normalizeTags = (raw: unknown): string[] => {
  if (Array.isArray(raw)) {
    return uniqueOrder(raw.map(String));
  }
  if (typeof raw === 'string') {
    // Server liefert "t1||t2"
    return uniqueOrder(raw.split('||'));
  }
  return [];
};

const NameInfo: React.FC<{ info: PointItem }> = ({ info }) => {
  const names = [info.current_name, info.name, info.group_name].filter(Boolean) as string[];
  const namepath = names.join(' / ');

  if (info.name) {
    return (
      <div
        style={{
          fontFamily: 'Roboto, sans-serif',
          fontWeight: 500,
          fontSize: '18px',
          lineHeight: '100%',
          letterSpacing: '0%',
          verticalAlign: 'middle',
          color: 'rgba(68, 68, 68, 1)',
        }}
      >
        {info.name}
      </div>
    );
  }

  return (
    <div
      style={{
        fontFamily: 'Roboto, sans-serif',
        fontWeight: 400,
        fontSize: '16px',
        color: 'rgba(68, 68, 68, 1)',
      }}
    >
      {namepath || 'N/A'} {}
    </div>
  );
};

const CountInfo: React.FC<{ count?: number | null }> = ({ count }) => {
  if (count == null) return null;
  return (
    <Typography variant="h6" component="div" color="secondary">
      <Trans>Ticket left: </Trans> {count}
    </Typography>
  );
};

const TextInfo: React.FC<{ info: PointItem; isExternal?: boolean }> = ({ info, isExternal }) => {
  let dateStr = '--';
  try {
    if (info.created_at) {
      const dateObj = new Date(info.created_at);
      if (!isNaN(dateObj.getTime())) {
        const dd = String(dateObj.getDate()).padStart(2, '0');
        const mm = String(dateObj.getMonth() + 1).padStart(2, '0');
        const yy = String(dateObj.getFullYear()).slice(-2);
        dateStr = `${dd}.${mm}.${yy}`;
      }
    }
  } catch (e) {
    console.error('Error formatting date:', e);
  }

  const handleIDClick = () => {
    if (info.ticket_id) {
      window.location.href = `/ShowTask/${info.ticket_id}`;
    }
  };

  return (
    <Info>
      <Box display="flex" justifyContent="space-between" alignItems="center">
        <StyledDate>{dateStr}</StyledDate>
        {!isExternal && info.ticket_id && <StyledID onClick={handleIDClick}>#{info.ticket_id}</StyledID>}
      </Box>

      <Box mt={0.5}>
        <NameInfo info={info} />
      </Box>

      <hr style={{ margin: '0.5em 0' }} />

      {info.comment && <StyledComment>{info.comment}</StyledComment>}

      <CountInfo count={info?.open_tickets} />
    </Info>
  );
};

export type CardProps = {
  isExternal?: boolean;
  info: PointItem;
  handleMoreInfoClick: () => void;
};

const handleNextTaskWithAction = (props: CardProps) => {
  const lng = (props.info as any).long_id;
  if (!lng) {
    console.warn('long_id is missing, cannot open next task form.');
    return;
  }
  const url = `form?byid=${lng}`;
  // @ts-ignore
  window.openFormPopup?.(url);
};
const RADIUS = '6px';

const AddTagWrap = styled(Box)`
  display: flex;
  align-items: center;
  gap: 6px;
`;

const AddIconBtn = styled(IconButton)`
  width: 28px !important;
  height: 28px !important;
  border-radius: ${RADIUS} !important;
  border: 1px solid rgba(0, 0, 0, 0.12) !important;
  background-color: transparent !important;
  box-shadow: none !important;
  padding: 0 !important;
  &:hover {
    background-color: var(--Google-Backround, rgba(236, 244, 254, 1)) !important;
  }
`;

const InlineInput = styled(TextField)`
  & .MuiInputBase-input {
    font-family: 'Roboto';
    font-size: 13px;
    padding: 4px 8px;
  }
`;

const StyledActionButton = styled.div`
  display: flex;
  align-items: center;
  padding: 6px 8px;
  border-radius: 4px;
  cursor: pointer;
  outline: none;
  border: none;
  background: transparent;
  font-family: 'Roboto', sans-serif;
  font-size: 13px;
  color: #333;
  gap: 6px;

  &:hover {
    background-color: rgba(158, 158, 158, 0.2);
  }

  img {
    height: 20px;
    width: auto;
  }

  span {
    line-height: 1;
  }
`;

/** --- Card: integriert Tags in Footer --- */
const Card = (props: CardProps) => {
  const { info, handleMoreInfoClick, isExternal } = props;

  const [grpPath, setGrpPath] = useState<string>('');

  // --- Tags ---
  // Normalisiert aus info.tags (Array ODER "t1||t2")
  const normalizedFromInfo = useMemo(() => normalizeTags((info as any)?.tags), [(info as any)?.tags]);
  const [tags, setTags] = useState<string[]>(normalizedFromInfo);

  // Aktualisiere lokalen State, wenn sich tags oder long_id ändern
  useEffect(() => {
    setTags(normalizedFromInfo);
  }, [normalizedFromInfo, (info as any)?.long_id]);

  async function addTicketTag(ticketId: string | number, tag: string): Promise<void> {
    const resp = await fetch(`/api/c/${ticketId}/tags`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ tag }),
    });
    if (!resp.ok) {
      const txt = await resp.text().catch(() => '');
      throw new Error(`Failed to add tag: ${resp.status} ${txt}`);
    }
  }

  async function removeTicketTag(ticketId: string | number, tag: string): Promise<void> {
    const resp = await fetch(`/api/c/${ticketId}/tags/${encodeURIComponent(tag)}`, {
      method: 'DELETE',
    });
    if (!resp.ok) {
      const txt = await resp.text().catch(() => '');
      throw new Error(`Failed to remove tag: ${resp.status} ${txt}`);
    }
  }

  // --- Add-Tag UI State ---
  const [showInput, setShowInput] = useState(false);
  const [newTag, setNewTag] = useState('');

  const handleAddClick = () => {
    if (!(info as any)?.long_id && !(info as any)?.ticket_id) return;
    setShowInput((v) => !v);
    setNewTag('');
  };

  const handleKeyDown: React.KeyboardEventHandler<HTMLInputElement> = async (e) => {
    if (e.key === 'Escape') {
      setShowInput(false);
      setNewTag('');
      return;
    }
    if (e.key !== 'Enter') return;

    const tag = newTag.trim();
    const id = (info as any)?.long_id ?? (info as any)?.ticket_id;
    if (!tag || !id) return;

    // Duplikate clientseitig vermeiden
    const exists = tags.some((t) => t.trim().toLowerCase() === tag.toLowerCase());
    if (exists) {
      setShowInput(false);
      setNewTag('');
      return;
    }

    try {
      await addTicketTag(id, tag);
      // optimistisch lokalen State erweitern (mit Dedupe)
      setTags((prev) => uniqueOrder([...prev, tag]));
      setShowInput(false);
      setNewTag('');
    } catch (err) {
      console.error(err);
      // optional: Snackbar
    }
  };

  const handleBlur: React.FocusEventHandler<HTMLInputElement> = () => {
    setShowInput(false);
    setNewTag('');
  };

  const handleRemoveTag = async (tag: string) => {
    const id = (info as any)?.long_id ?? (info as any)?.ticket_id;
    if (!id) return;

    const ok = await window.confirmPopup({
      title: 'Tag entfernen',
      message: (
        <span>
          Der Tag <b>{tag}</b> wird von diesem Eintrag entfernt. Fortfahren?
        </span>
      ),
      confirmLabel: 'Entfernen',
      cancelLabel: 'Abbrechen',
      danger: true,
    });
    if (!ok) return;

    try {
      await removeTicketTag(id, tag);
      setTags((prev) => prev.filter((t) => t !== tag));
    } catch (err) {
      console.error(err);
    }
  };

  const handleOpenPdf = () => {
    if (info.ticket_id) {
      const url = `/comment/pdf/${info.ticket_id}`;
      const name = `pdf_report_${info.ticket_id}`;
      window.open(url, name, 'width=800,height=600,resizable=yes,scrollbars=yes');
    } else {
      console.warn('ticket_id is missing, cannot open PDF.');
    }
  };

  useEffect(() => {
    if (!info.ticket_id) {
      setGrpPath('');
      return;
    }
    async function fetchGroupPath() {
      try {
        const response = await fetch(`/api/cards/list/${info.ticket_id}`);
        if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
        const data = await response.json();

        if (data && data.fullPath && data.fullPath.length > 0) {
          const entry = data.fullPath[0];
          if (entry && entry.full_path && typeof entry.full_path === 'string' && entry.bereich_name) {
            const rawPath = entry.full_path.replace(/^\/+/, '').split('/');
            rawPath.shift();
            rawPath.reverse();
            const fullDisplay = [entry.bereich_name, ...rawPath].join(' / ');
            setGrpPath(fullDisplay);
          } else {
            setGrpPath('Path data incomplete');
          }
        } else {
          setGrpPath('No path data found');
        }
      } catch (err) {
        console.error('Failed to fetch group path:', err);
        setGrpPath('Error loading path');
      }
    }
    fetchGroupPath();
  }, [info.ticket_id]);

  return (
    <StyledCard>
      <Color color={(info as any).color} />
      <FillAvailable>
        <TextInfo info={info} isExternal={isExternal} />
        <FooterRow>
          <GroupName>{grpPath || 'Loading path...'}</GroupName>

          <TagRow>
            <Box display="flex" gap={0.5} flexWrap="wrap">
              {tags.map((t, idx) => (
                <Box
                  key={`${t}-${idx}`}
                  sx={{
                    position: 'relative',
                    display: 'inline-flex',
                    '&:hover > .card-tag-delete': {
                      opacity: 1,
                      visibility: 'visible',
                    },
                  }}
                >
                  <Chip
                    label={t}
                    size="small"
                    style={{
                      fontFamily: 'Roboto',
                      fontSize: 12,
                      background: '#ecf4fe',
                      color: '#0099ff',
                      border: '1px solid rgba(0, 153, 255, 0.35)',
                      height: 22,
                    }}
                  />
                  <IconButton
                    className="card-tag-delete"
                    size="small"
                    onClick={(e) => {
                      e.stopPropagation();
                      handleRemoveTag(t);
                    }}
                    sx={{
                      position: 'absolute',
                      right: -6,
                      top: -6,
                      width: 18,
                      height: 18,
                      borderRadius: '50%',
                      opacity: 0,
                      visibility: 'hidden',
                      transition: 'opacity 120ms ease, visibility 120ms ease',
                      padding: 0,
                      zIndex: 1,
                      backgroundColor: '#fff',
                      boxShadow: '0 2px 6px rgba(0,0,0,0.1)',
                      border: '1px solid rgba(0,0,0,0.08)',
                      '& svg': { fontSize: 12 },
                      '&:hover': {
                        backgroundColor: 'rgba(0,0,0,0.04)',
                      },
                    }}
                  >
                    <CloseRoundedIcon />
                  </IconButton>
                </Box>
              ))}
            </Box>

            {showInput && (
              <InlineInput
                size="small"
                placeholder="Neuer Tag"
                variant="outlined"
                value={newTag}
                onChange={(e) => setNewTag(e.target.value)}
                onKeyDown={handleKeyDown}
                onBlur={handleBlur}
                autoFocus
              />
            )}
          </TagRow>

          <IconContainer>
            <StyledActionButton onClick={() => handleNextTaskWithAction(props)}>
              <img src="/icon8/okNext24.png" alt="next task icon" />
            </StyledActionButton>

            <AddTagWrap>
              <Tooltip title="Tag hinzufügen" arrow>
                <AddIconBtn size="small" onClick={handleAddClick} aria-label="Add tag">
                  <AddIcon fontSize="small" />
                </AddIconBtn>
              </Tooltip>
            </AddTagWrap>

            <img
              src="/imgtasko/pdf.png"
              height="22px"
              alt="PDF"
              onClick={handleOpenPdf}
              style={{ cursor: 'pointer' }}
            />
            <img
              src="/icon8/infoButton.png"
              alt="Info"
              height="20px"
              onClick={handleMoreInfoClick}
              style={{ cursor: 'pointer' }}
            />
          </IconContainer>
        </FooterRow>
      </FillAvailable>
    </StyledCard>
  );
};

export default Card;

// ---- Tag-Filter (in Card.tsx) ---------------------------------------------

const norm = (s: unknown) => String(s ?? '').trim().toLowerCase();
const getKey = (it: any) => String(it?.long_id ?? '');

// akzeptiert Array oder "t1||t2"
const normalizeTagsLoose = (raw: unknown): string[] => {
  if (Array.isArray(raw)) return uniqueOrder(raw.map(String));
  if (typeof raw === 'string') return uniqueOrder(raw.split('||'));
  return [];
};

export const CardTagFilter: React.FC<{
  cardDetails: any[] | null | undefined; // Items können tags als string[] ODER "a||b" liefern
  children: (filtered: any[]) => React.ReactNode;
}> = ({ cardDetails, children }) => {
  const [selectedTags, setSelectedTags] = useState<string[]>([]);

  // Map: ticketKey -> tags[]
  const tagsByTicket = useMemo(() => {
    if (!Array.isArray(cardDetails)) return {} as Record<string, string[]>;
    const map: Record<string, string[]> = {};
    for (const it of cardDetails) {
      const k = getKey(it);
      if (!k) continue;
      map[k] = normalizeTagsLoose(it?.tags);
    }
    return map;
  }, [cardDetails]);

  // Sichtbare Tags aus den aktuellen Cards (Original-Schreibweise bewahren)
  const visibleTags = useMemo(() => {
    if (!Array.isArray(cardDetails)) return [] as string[];
    const seen = new Map<string, string>();
    for (const it of cardDetails) {
      const k = getKey(it);
      if (!k) continue;
      const list = Array.isArray(tagsByTicket[k]) ? tagsByTicket[k] : [];
      for (const t of list) {
        const lower = norm(t);
        if (!seen.has(lower)) seen.set(lower, t);
      }
    }
    return Array.from(seen.values()).sort((a, b) => a.localeCompare(b));
  }, [cardDetails, tagsByTicket]);

  // OR-Filter: zeige Items, die mind. einen der ausgewählten Tags haben
  const filtered = useMemo(() => {
    if (!Array.isArray(cardDetails)) return [] as any[];
    if (!selectedTags.length) return cardDetails;

    const needles = selectedTags.map(norm);
    return cardDetails.filter((it) => {
      const k = getKey(it);
      if (!k) return false;
      const list = (tagsByTicket[k] || []).map(norm);
      return needles.some((n) => list.includes(n));
    });
  }, [cardDetails, selectedTags, tagsByTicket]);

  // ausgewählte Tags auf sichtbare reduzieren (falls sich Cards ändern)
  useEffect(() => {
    if (!selectedTags.length) return;
    const vis = new Set(visibleTags.map(norm));
    const next = selectedTags.filter((t) => vis.has(norm(t)));
    if (next.length !== selectedTags.length) setSelectedTags(next);
  }, [visibleTags, selectedTags]);

  return (
    <>
      {/* Tag-UI */}
      <div style={{ margin: '0 0 12px 0' }}>
        <Autocomplete
          multiple
          size="small"
          options={visibleTags}
          value={selectedTags}
          onChange={(_, v) => setSelectedTags((v ?? []).filter(Boolean))}
          isOptionEqualToValue={(o, v) => String(o) === String(v)}
          filterSelectedOptions
          clearOnEscape
          disableCloseOnSelect
          noOptionsText={<Trans>No options</Trans>}
          renderTags={(value, getTagProps) =>
            value.map((option, index) => (
              <Chip
                {...getTagProps({ index })}
                key={option}
                label={option}
                size="small"
                variant="outlined"
                sx={{
                  fontFamily: 'Roboto',
                  fontSize: 14,
                  fontWeight: 500,
                  borderRadius: '10px',
                  '& .MuiChip-deleteIcon': { opacity: 0.7, '&:hover': { opacity: 1 } },
                  '&:hover': {
                    backgroundColor: 'var(--Google-Backround, rgba(236,244,254,1))',
                    color: 'var(--Google-Blau, rgba(0,153,255,1))',
                  },
                }}
              />
            ))
          }
          renderInput={(params) => (
            <TextField
              {...params}
              placeholder={selectedTags.length === 0 ? 'Filter by Tags' : ''}
              variant="outlined"
              label={<Trans>Tags</Trans>}
              InputProps={{
                ...params.InputProps,
                sx: {
                  padding: '4px 8px',
                  '& fieldset': { borderColor: 'rgba(0,0,0,0.2)' },
                  '&:hover fieldset': { borderColor: 'rgba(0,0,0,0.5)' },
                  '&.Mui-focused fieldset': { borderColor: 'rgba(0,0,0,0.8)' },
                },
              }}
              sx={{ '& .MuiInputBase-input': { fontFamily: 'Roboto', fontSize: 14 } }}
            />
          )}
          style={{ width: 240 }}
        />
      </div>

      {/* Gefilterte Liste zurückgeben */}
      {children(filtered)}
    </>
  );
};
